Mongo Query question $gt,$lt

2019-01-14 11:59发布

问题:

I have a query below. I want get items between 4 and 6 so only a:1 should match because it has the value 5 in b.

> db.test.find({ b : { $gt :  4  }, b: {$lt : 6}});
{ "_id" : ObjectId("4d54cff54364000000004331"), "a" : 1, "b" : [ 2, 3, 4, 5 ] }
{ "_id" : ObjectId("4d54d0074364000000004332"), "a" : 2, "b" : [ 2, 4, 6, 8 ] }
>

Can someone tell be why a:2 is matching this query? I can't really see why it is being returned.

I also tried what was specified in the tutorial but id did not seem to work:

> db.test.find({ b : { $gt :  4, $lt : 6}});
{ "_id" : ObjectId("4d54cff54364000000004331"), "a" : 1, "b" : [ 2, 3, 4, 5 ] }
{ "_id" : ObjectId("4d54d0074364000000004332"), "a" : 2, "b" : [ 2, 4, 6, 8 ] }
>

And this one to avoid any confusion regarding GT/GTE

> db.test.find({b: {$gt: 4.5, $lt: 5.5}});
{ "_id" : ObjectId("4d54cff54364000000004331"), "a" : 1, "b" : [ 2, 3, 4, 5 ] }
{ "_id" : ObjectId("4d54d0074364000000004332"), "a" : 2, "b" : [ 2, 4, 6, 8 ] }
>

only a:1 should be returned.

As suggested, I gave $elemMatch a try but it did not appear to work either (objectIds are different because I am on a different machine)

> db.test.find();
{ "_id" : ObjectId("4d5a24a5e82e00000000433f"), "a" : 1, "b" : [ 2, 3, 4, 5 ] }
{ "_id" : ObjectId("4d5a24bbe82e000000004340"), "a" : 2, "b" : [ 2, 4, 6, 8 ] }
> db.test.find({b: {$elemMatch: {$gt : 4, $lt: 6 }}});
>

No documents were returned.

回答1:

This is a really confusing topic. I work at 10gen and I had to spend a while wrapping my head around it ;)

Let's walk through how the query engine processes this query.

Here's the query again:

> db.test.find({ b : { $gt :  4, $lt : 6}});

When it gets to the record that seems like it shouldn't match...

{ "_id" : ObjectId("4d54cff54364000000004331"), "a" : 1, "b" : [ 2, 4, 6, 8 ] }

The match is not performed against each element of the array, but rather against the array as a whole.

The comparison is performed in three steps:

Step 1: Find all documents where b has a value greater than 4

b: [2,4,6,8] matches because 6 & 8 are greater than 4

Step 2: Find all documents where b has a value less than 6

b: [2,4,6,8] matches because 2 & 4 are less than 6

Step 3: Find the set of documents that matched in both step 1 & 2.

The document with b: [2,4,6,8] matched both steps 1 & 2 so it is returned as a match. Note that results are also de-duplicated in this step, so the same document won't be returned twice.

If you want your query to apply to the individual elements of the array, rather than the array as a whole, you can use the $elemMatch operator. For example

> db.temp.find({b: {$elemMatch: {$gt: 4, $lt: 5}}})
> db.temp.find({b: {$elemMatch: {$gte: 4, $lt: 5}}})
  { "_id" : ObjectId("4d558b6f4f0b1e2141b66660"), "b" : [ 2, 3, 4, 5, 6 ] }


回答2:

$gt

Syntax: {field: {$gt: value} }

eg:

db.inventory.find( { qty: { $gt: 20 } } )

$lt

Syntax: {field: {$lt: value} }

eg:

db.inventory.find( { qty: { $lt: 20 } } )

eg2:

db.inventory.find({ qty : { $gt :  20, $lt : 60}});


回答3:

.find( {$and:[ {b:{$gt:4}}, {b:{$lt:6}} ]} )


回答4:

Because you did not check the documentation.

See

http://www.mongodb.org/display/DOCS/Advanced+Queries

and check for "ranges" on the page.

Neither is your query syntax correct (compare against the example)

nor does your "why a:2" part of the question make any sense since 'a' is not involved in your query. If you want to search for a:1 then you have to include it in your query.

Keep in mind that all query clauses are AND combined by default unless you use the $or operator.



标签: mongodb