Reputation: 919
Given this:
{ _id: 1, results: [ {a: 82, b: 81}, {a: 82, b: 88} ] }
{ _id: 2, results: [ {a: 82, b: 90}, {a: 82, b: 33} ] }
I want to find the docs which have no results with a or b less than 80. (doc 1 in this case) I know I could use $elemMatch to find the docs with any result containing an a or b less than 80. Is there a way to do the reverse?
Alternatively, I could rewrite my conditions to find docs where all results have a and b greater than 79. Is there an operator which does that?
Upvotes: 1
Views: 75
Reputation: 5908
Yes, the opposite of $lt
is $gt
, which returns all documents that have a certain attribute greater than the specified value.
db.collection.find({results: {$elemMatch: { $and: [{a: {$gt: 79}}, {b: {$gt: 79}}]}}});
EDIT: I have further investigated and it appears that $elemMatch
only checks the first element of the array. I have also checked the solution provided by wdberkeley and it works just as intended. Apart from the query built by wdberkeley, the only alternative would be to use the aggregation framework, but that would be far more complex than a simple find query.
Upvotes: 0
Reputation: 11671
Use $not
and $or
:
db.test.find({ "results" : {
"$not" : {
"$elemMatch" : {
"$or" : [
{ "a" : { "$lt" : 80 } },
{ "b" : { "$lt" : 80 } }
]
}
}
} })
The negation of your condition is "documents with some result having a
or b
values less than 80". I wrote a query for that, and negated it. Given the way queries work on array elements, I believe it is generally necessary to use $not
to enforce a condition on every array element.
Upvotes: 2