Reputation: 325
The starting point is a collection that looks like this:
{
"_id" : ObjectId("55b3c75d84251af91782ea07"),
"arr" : [
{
"val" : "yes"
},
{
"val" : "yes"
}
]
}
{
"_id" : ObjectId("55b3c76184251af91782ea08"),
"arr" : [
{
"val" : "yes"
},
{
"val" : "no"
}
]
}
...
What I want to find are documents that only have yes
's in arr.val
. Please note that you will need to use findAndModify
because I will need to update the documents afterwards.
What I've tried:
> db.coll.find({arr: {$all: [{$elemMatch: {val: 'yes'}}]}})
{ "_id" : ObjectId("55b3c75d84251af91782ea07"), "arr" : [ { "val" : "yes" }, { "val" : "yes" } ] }
{ "_id" : ObjectId("55b3c76184251af91782ea08"), "arr" : [ { "val" : "yes" }, { "val" : "no" } ] }
> db.coll.find({arr: {$all: [{val: 'yes'}]}})
{ "_id" : ObjectId("55b3c75d84251af91782ea07"), "arr" : [ { "val" : "yes" }, { "val" : "yes" } ] }
{ "_id" : ObjectId("55b3c76184251af91782ea08"), "arr" : [ { "val" : "yes" }, { "val" : "no" } ] }
Both versions still find both documents.
Upvotes: 0
Views: 53
Reputation: 311895
You can do this using a combination of $eq
and $ne
to find docs that contain at least one arr
element where val
is 'yes'
, and no elements where its value is 'no'
:
db.coll.find({"arr.val": {$eq: 'yes', $ne: 'no'}})
Matches just the first doc:
{
"_id" : ObjectId("55b3c75d84251af91782ea07"),
"arr" : [
{
"val" : "yes"
},
{
"val" : "yes"
}
]
}
In a findAndModify
:
db.coll.findAndModify({
query: {"arr.val": {$eq: 'yes', $ne: 'no'}},
update: {$set: {a: 1}},
new: true
})
Upvotes: 1