Ok, so I'm trying to roll out a small update to my site. One update includes querying upon a field that may or may not exist. This doesn't work as I want, so I decided to just make it so that the field always exists in my database. I used this line at the MongoDB shell:
> db.entries.update({Published: null},{$set: {Published: true}},false,true);
Now, I'm not fully understanding how this caused every entry object where Published is null to be deleted. I mean, it literally was deleted. I tried looking up some IDs, and .findOne will return null for them.
How does that line work? I thought it would take every entry where Published is null(doesn't exist), and set Published to true.
Reading about operator behavior is better than guessing operator behavior. Search for null is different from performing a check for existence.
MongoDB has a dedicated $exists operator:
http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24exists
To be honest, I'm not sure why it now works with changes, or at least, why it deleted everything with that command.
My ending command looked like this:
db.entries.update({Published: {$exists: false},$atomic: true},{$set:{"Published":true}},false,true);
I thought it would take every entry where Published is null(doesn't exist), and set Published to true.
OK, so these are two different things.
Published is null:
{ Published : null, post : 'blah' }
Published does not exist:
{ post : 'blahblah' }
You may want to post this question over at the MongoDB user group (developers check it very often) at http://groups.google.com/group/mongodb-user
Updates do not delete documents. In fact, the update you ran does what you intended, for example, if you wanted y to always have a value:
> db.foo.insert({x:1})
> db.foo.insert({x:2})
> db.foo.insert({y:null})
> db.foo.insert({y:1})
> db.foo.update({y:null},{$set : {y:true}}, false, true)
> db.foo.find()
{ "_id" : ObjectId("4db02aabbe5a5418fb65d24c"), "y" : true }
{ "_id" : ObjectId("4db02aafbe5a5418fb65d24d"), "y" : 1 }
{ "_id" : ObjectId("4db02aa1be5a5418fb65d24a"), "x" : 1, "y" : true }
{ "_id" : ObjectId("4db02aa4be5a5418fb65d24b"), "x" : 2, "y" : true }
There must have been another operation that did the delete. There might be a record of it in the logs (or there might not... it depends how long it took). It's impossible to tell from the info here what caused the deletions, but the update isn't the culprit here.
Related
So i have a program constantly running watching an API endpoint. When something on the endpoint has changed, it updates the mongodb document exactly how I want it. Next, I want to be able to get what has changed in the document, and lets just say use that has a variable or whatever i decide to do with it. Right now, I can get it to update and just tell me that the document has been changed, but not get what EXACTLY has changed.
If you are replacing the document, you cannot get what was changed, but you can get the version of the document before the change was applied, so you can figure out the differences. In the official mongodb driver, use the FindOneAndReplace function to get the document as it was before the update, and then compare.
You can use:
read mongo log, or
write a code to compare between original data and updated data, or
you can add 1 more field which is updated to data
If you want more detailed version, I suggest you use mongo log mongoDB Profiler section Update Operation.
Here is the snippet of the log:
{
"op" : "update",
"ns" : "test.report",
"command" : {
"q" : { },
"u" : { "$rename" : { "a" : "b" } },
"multi" : true,
"upsert" : false
},
.............
Hope it helps.
After upgrade to 3.0 mongo driver i am receiving some new error on update request. For update like this:
db.table.update({_id: .... } , {$set : { "tags.Tag1" : true }});
I am receiving
cannot use the part (tags of tags.Tag1) to traverse the element ({tags: null})]]
The problem is that my updated document already contains default value for tags : null. If I manually remove it from document , update starts to work correctly. It is some new behavior for me , and it is happens after updating mongo driver from 2 to 3 ( not even database itself).
But now I wonder now how to avoid this error. I can of course check if "tags" already defined and only then make $set to element or the whole map. But it means 3 requests vs one old and the other problems like atomicity.
Although it's an old post but I think what you are looking for is the $ positional operator
I am guessing your "tags" is an array. So the above example could be something like
db.table.update({_id: .... } , {$set : { "tags.$.Tag1" : true }});
Hope it helps!
Yes, it can be updated... I had resolved similar problem
Resolved this
db.table.updateById({_id: .... } , {$set : { "levelSpecificData.scale.uom": "feet"}});
5b1f566ed65c7dcc34aaa7d5 MongoError: cannot use the part (scale of levelSpecificData.scale.uom) to traverse the element ({scale: false})
where in my collection 'levelSpecificData.scale' was a Boolean type T/F
I changed the default value type of levelSpecificData.scale to '{}' empty object... Surprisingly it worked fine after changing default values to object, since I want to treat scale as an object reference this solution was all good for it.
Okay, I'm a SQL Server based DBA, but there's a biz-critical app that uses MongoDB as a core component, and the problem is that it's grown too large. (The "large-ness" isn't critical yet, I'm trying to be proactive!)
Specifically, it has a "message log" collection which is over 400 GB, where the date-stamp is actually stored as a 2-element array [Int64, Int32], the 0th element being some measure of time (and the 1th element is just always '0').
So for example, a document:
{
"_id" : ObjectId("55ef63618c782e0afcf346cf"),
"CertNumber" : null,
"MachineName" : "WORKERBEE1",
"DateTime" : [
NumberLong(635773487051900000),
0
],
"Message" : "Waited 00:00:30.0013381 to get queue lock: Specs to verify",
"ScopeStart" : false
}
And just because 2 is better than 1, another example document:
{
"_id" : ObjectId("55ef63618c782e0afcf323be"),
"CertNumber" : null,
"MachineName" : "WORKERBEE2",
"DateTime" : [
NumberLong(635773487056430453),
0
],
"Message" : "Waited 00:00:30.0012345 to get queue lock: Specs to verify",
"ScopeStart" : false
}
I need to figure out two things:
What the heck does that "DateTime" really mean? It's not Unix Epoch time (seconds nor milliseconds); and even if I strip off the trailing 0's, it represents (in millis) 6/20/2171, so, unless we're building a time machine here, it makes no sense. If I strip off the last 6 digits, it means 2/23/1990, but even that doesn't seem likely, as this application has only existed since the early 2000's. (AFAIK)
Assuming we figure out #1, can we use some kind of command to remove (delete) all documents in the collection that are older than, say, 1/1/2016?
Again, I'm a SQL guy, so try to explain using analogs in that vein, e.g. "this is like your WHERE clause" and such.
PS: Yes, I read thru questions such as Find objects between two dates MongoDB and How do I convert a property in MongoDB from text to date type? , but so far nothing has jumped out at me.
There is extremely weird thing happening on my database. I have a query:
db.Tag.find({"word":"foo"})
this thing matches one object. it's nice.
Now, there's second query
db.Tag.find({$or: [{"word":"foo"}]})
and the second one does not give any results.
There's some kind of magic I obviously don't understand :( What is wrong in second query?
in theory, $or requires two or more parameters, so I can fake it with:
db.Tag.find({$or: [{"word":"foo"},{"word":"foo"}]})
but still, no results.
Your second query is perfectly fine, and it should work. Though the docs says, that $or performs logical operation on array of two or more expression, but it would work for single expression also.
Here's a sample that you can see, and try out, to get it to work: -
> db.col.insert({"foo": "Rohit"})
> db.col.insert({"foo": "Aman", "bar": "Rohit"})
>
> db.col.find({"foo": "Rohit"})
{ "_id" : ObjectId("50ed6bb1a401d9b4576417f7"), "foo" : "Rohit" }
> db.col.find({$or: [{"foo": "Rohit"}]})
{ "_id" : ObjectId("50ed6bb1a401d9b4576417f7"), "foo" : "Rohit" }
So, as you can see, both your query when used for my collection works fine. So, there is certainly something wrong somewhere else. Are you sure you have data in your collection?
Okaay, server admin installed mongodb from debian repo. Debian repo had 1.4.4 version of mongodb, aandd looks like $or is simply not yet supported out there :P
First, I'd like to say that I really love NoSQL & MongoDB but I've got some major concerns with its schema-less aspect.
Let's say I have 2 tables. Employees and Movies.
And... I have a very stupid data layer / framework that sometimes like to save objects in the wrong tables.
So one day, a Movie gets saved in the Employees table. Like this:
> use mongoTests;
switched to db mongoTests
> db.employees.insert({ name : "Max Power", sex : "Male" });
> db.employees.find();
{ "_id" : ObjectId("4fb25ce6420141116081ae57"), "name" : "Max Power", "sex" : "Male" }
> db.employees.insert({ title : "Fight Club", actors : [{ name : "Brad Pitt" }, { name : "Edward Norton" }]});
> db.employees.find();
{ "_id" : ObjectId("4fb25ce6420141116081ae57"), "name" : "Max Power", "sex" : "Male" }
{ "_id" : ObjectId("4fb25db834a31eb59101235b"), "title" : "Fight Club", "actors" : [ { "name" : "Brad Pitt" }, { "name" : "Edward Norton" } ] }
This is VERY wrong.
Let's switch the context, think about Movies, and CreditCards (for whatever reason, in this context credit cards would be stored in clear text inside the DB). This is SUPER WRONG?
The code would probably explode because it's trying to use an object
structure and receives another totally unknown structure.
Even worst, the code actually works and the webstore visitors
actually see credit cards information in the "Rent a movie" list.
Is there anything, built-in that would prevent such threat to ever happen? Like some way to "force" a schema to be respected for only some tables?
Or is there any way to force MongoDB to make a schema mandatory? (Can't create new fields in a table, etc)
EDIT: For those who thinks I'm trolling, I'm really not, this is an important question for me and my team because this is a big decision whether or not we're going to use NoSQL.
Thanks and have a nice day.
The schema-less aspect is one of the major positives.
A DB with a schema doesn't fully remove this kind of issue - e.g. there could be a bug in a system that uses a RDBMS that puts the wrong data in the wrong field/table.
IMHO, the bigger concern would be, how did that kind of bug make it through dev, testing and out into production?!
Having said that, you could set up a process that checks the "schema" of documents within a collection (e.g. look at newly added documents, check whether they have fields you would expect to see in there) - then flag up for investigation. There is such a tool (node.js) here (I think, I've never used it):
http://dhendo.github.com/node-mongodb-schema-validator/
Edit:
For those finding this question in future, so the link in my comment doesn't go overlooked, there's a jira item for this kind of thing here:
http://jira.mongodb.org/browse/SERVER-3536