Using $where to compare against nested field - mongodb

I have a mongodb collection with documents of the following structure (simplifying it, the numbers are just for example):
{'a' : 1, 'b' : {'c':2}}
I want to run the following mongodb query:
{'$where' : 'this.a < this.b.c'}
The above doesn't work.
What is the correct syntax for such a query ?

Found the issue: not all of my collection documents contained the "b" value, and thus I was receiving an error:
db.alerts.find({$where:"this.a < this.b.c"})
error: {
"$err" : "TypeError: Cannot read property 'c' of undefined",
"code" : 16722
}
Fixed by changing my query to:
{"b.c":{$exists : true}, $where : "this.c < this.b.c"}

Related

mongodb length of a property

Documents present in my collection,
"info"{name : "sample"}, "extraInfo"{ tempCode :"1020200", newCode :"3844"}
I want to get all the documents having the newCode length > 3. I have tried below way,db.collection.find({$where:"this.extraInfo.newCode.length > 3"})
which returns result as
{
"code" : 16722
}
use {$exists:true} in order to get it right
db.collection.find({"newCode" : {$exists:true}, $where:"this.extraInfo.newCode.length > 3"})

compare multiple value in same document in mongodb

My question was, how to find all title of the releases contains the artist name
Here is the 2 Documents for just an example:
`{"release" : {"title" : "DEF day",
"artists" : {"artist" : {"role" : "1","name" : "DEF"}}}
}
{ "release" : {"title" : "XYZ day",
"artists" : {"artist" : {"role" : "1","name" : "KYC"}}}
}`
when i run this following query:
`db.test.find({$where:
"this.release.title.indexOf(this.release.artists.artist.name) > -1"
})`
I get the result "DEF day", so it works excellent!!
BUT, once i run this query to my original data(same format like above) i get this:
`error: {
"$err" : "TypeError: Object 30 has no method 'indexOf'\n at _funcs1 (_funcs1:1:49) near 'his.release.artists.a' ",
"code" : 16722
}`
My collection is big (8GB+).
Just looking at the above error, can anyone tell what may be the problem with the above query? your answer is appreciated. please.
The problem is in the data itself. Somewhere you have a document, where the title field is not String, thus invoking indexOf on the whole data, on that particular document you get the error.
One thing you can do to solve this problem is first of all find that erroneous document. To do that you will need to run a simple query.
MongoDB has the $type operator, which matches fields by their type. And here is the list of all available BSON types a MongoDB document field can have.
The id of String BSON type is 2, thus you need all the documents that have type of title field not equal to 2.
find({field: {$not: {$type: <BSON type>}}}))
After finding the document(s), you may fix or remove them.

Mongo db pulling part of the document

I've a document which has another nested document in it represent a changes (logging). Each change document has a timestamp, field, old and new values. Basically as you can see this document would grow a lot, and I really don't want to get all changes but only a recent one.
What I want to do is make a query and get only those changes which falls in between two time stamps. I am not interested in any other information in document, so I dont want to pull it, just recent changes.
{
.......
"adwordsChanges":[
{
"timestamp":NumberLong("1400162491325"),
"field":"syncState",
"old":null,
"new":"OK"
},
{
"timestamp":NumberLong("1400162491325"),
"field":"keywordId",
"old":null,
"new":NumberLong("23918779329")
},
{
"timestamp":NumberLong("1400162491325"),
"field":"adGroupId",
"old":null,
"new":NumberLong("16972286472")
}
]
}
This is what I've tried!
db.keywords.find(
{
$and :[{"_id" : ObjectId("5374c7a7ac58b0d3b5e970fa")}, {"adwordsChanges.field" : "keywordId"}, {"adwordsChanges.timestamp" : {$gte:NumberLong("11111111"), $lte:NumberLong(99999999999999) }}]
})
Running Andrei's query I am getting compilation error:
assert: command failed: {
"errmsg" : "exception: The top-level _id field is the only field currently supported for exclusion",
"code" : 16406,
"ok" : 0
} : aggregate failed
Error: command failed: {
"errmsg" : "exception: The top-level _id field is the only field currently supported for exclusion",
"code" : 16406,
"ok" : 0
} : aggregate failed
at Error (<anonymous>)
at doassert (src/mongo/shell/assert.js:11:14)
at Function.assert.commandWorked (src/mongo/shell/assert.js:244:5)
at DBCollection.aggregate (src/mongo/shell/collection.js:1149:12)
at (shell):1:13
2014-05-27T15:23:54.945+0100 Error: command failed: {
"errmsg" : "exception: The top-level _id field is the only field currently supported for exclusion",
"code" : 16406,
"ok" : 0
Thanks for any help!
You could use aggregation framework to filter subdocuments, like this:
db.keywords.aggregate({$unwind:"$adwordsChanges"},
{$match:{"adwordsChanges.timestamp" :
{$gte:1400162491325, $lte:23918779329},
"adwordsChanges.field" : "keywordId"}},
{$project:{_id:0,
timestamp:"$adwordsChanges.timestamp",
field:"$adwordsChanges.field",
old:"$adwordsChanges.old",
new:"$adwordsChanges.new"
}});
Explanation of difference between project and group
Initially I thought original document should be returned and group was used to restore original document structure, i.e in this case groupis opposite operation to unwind. After clarification it became clear that only subdocuments were needed, then I replaced group operation with project, so that subdocuments were projected to root level.

How to use WHERE clause in mongodb when the key of a field is numeric

Say I insert a document into mongo like below:
db.test.insert({1 : { 2 : "some value"}, 3 : { 4 :"some other value"}});
How do I use the $where clause to match this document? I tried using the following:
db.test.find({"$where" : "this.1.2 == this.3.4"});
but I ended up getting this error message.
error: {
"$err" : "JavaScript execution failed: SyntaxError: Unexpected number",
"code" : 16722
}
I know $where is not recommended, but say if I have to use it, is there any way to accomplish this? Thanks in advance.

Inserting a number into a list in a mongodb subdocument

I have a document in MongoDB of the form:
{"_id" : 1, "value" : { "listOfNumbers" : [2,3,4]}}
I can't seem to figure out, how to insert a new number into the "listOfNumbers". I found:
db.collection.update({_id:1}, {listOfNumbers : 8})
This only works if the above document would be of the form (a document without a sub document):
{"_id" : 1, "listOfNumbers" : [2,3,4]}
I tried playing around with all sorts of combinations, but none worked as expected.
Would anybody know the solution to this problem?
You should use the following syntax :
db.collection.update({_id:1}, {$push:{'value.listOfNumbers' : 8}})
It will push the value 8 in your array listOfNumbers