The query is good as it matches the document, but the "projection" is outside the scope of what you can do with .find()
, you need .aggregate()
and some care taken to not remove the "images" items from the array and only the non matching "tags".
Ideally you do this with MongoDB 3.2 using $filter
inside $project
:
db.site_users.aggregate([
{ "$match": { "images.tags": "broken" }},
{ "$project": {
"email": 1,
"password": 1,
"images": {
"$filter": {
"input": "$images",
"as": "image",
"cond": {
"$setIsSubSet": [["broken"], "$$image.tags"]
}
}
}
}}
])
Or possibly using $map
and $setDifference
which is also compatible with MongoDB 2.6, as long as the "images" content is "unique" for each entry. This is due to the "set" operation, in which "sets" are "unique":
db.site_users.aggregate([
{ "$match": { "images.tags": "broken" }},
{ "$project": {
"email": 1,
"password": 1,
"images": {
"$setDifference": [
{ "$map": {
"input": "$images",
"as": "image",
"in": {
"$cond": {
"if": { "$setIsSubSet": [["broken"], "$$image.tags" ] },
"then": "$$image",
"else": false
}
}
}},
[false]
]
}
}}
])
It can be done in earlier versions of MongoDB but is possibly best avoided due to the cost of processing $unwind
on the array:
db.site_users.aggregate([
{ "$match": { "images.tags": "broken" }},
{ "$unwind": "$images" },
{ "$match": { "images.tags": "broken" }},
{ "$group": {
"_id": "$_id",
"email": { "$first": "$email" },
"password": { "$first": "$password" },
"images": { "$push": "$images" }
}}
])
Since there is usually a considerable cost in using $unwind
for this purpose where you are not "aggregating" anything, then if you don't have a modern version where the other practical approaches are available, it's often best to accept "filtering" the array content itself in client code rather than on the server.
So you should only resort to $unwind
for this case where the array entries would be "significantly" reduced by order of removing the non-matching items. Otherwise the cost of processing is likely greater than the network cost of transferring the data, and any benefit is negated.
If you don't have a modern version, then get one. The features make all the difference to what is practical and performant.