Longli
Longli

Reputation: 29

nodejs + mongo + find + $and error: Can't canonicalize query

the query is:

{$and:[
    {phone:phone},
    {$gte:{date:'2014-08-25'}},
    {$lt:{date:'2014-08-30'}}
]}

and then it shows an error:

{ [MongoError: Can't canonicalize query: BadValue unknown top level operator: $gte] name: 'MongoError' }

What's the meaning of this error?

Upvotes: 1

Views: 1769

Answers (2)

Neil Lunn
Neil Lunn

Reputation: 151142

Your whole query structure is not correct really. Operators act on "fields" in a argument form. So the operator is a "value" to the field as a "key" in a manner of speaking.

Aside from that "all" MongoDB queries are in fact implicitly an "and" query. The $and operator itself is only required where you are specifying multiple conditions for the same field. But this is not how you do a "range query" with $gte and $lt operators, but rather you "combine" them in the same "operator document":

db.collection.find({
    "phone": phone,
    "date": { "$gte": "2014-08-25", "$lte": "2014-08-30" }
})

Also worth noting here that this only works where your dates are actually "strings". What you really "should" have are "date objects" in your collection, which generally represent in the shell like so:

ISODate("2014-08-29T17:51:30.428Z")

This will help you greatly as you can do other things with dates and similarly do not need to "convert" these for any other manipulation in your code. When you have actual "date objects" then you query them by simply using other date object instances like so:

db.collection.find({
    "phone": phone,
    "date": { "$gte": new Date("2014-08-25"), "$lte": new Date("2014-08-30") }
})

Upvotes: 3

Vadim
Vadim

Reputation: 17955

You need to do

{date: {$gte: '2014-08-25'}}

and likewise for the $lt

http://docs.mongodb.org/manual/reference/operator/query/gte/#op._S_gte

Upvotes: 1

Related Questions