Запрос хорош, как он совпадает с документом, но «проекция» выходит за рамки того, что вы можете сделать с .find()
, что вам нужно .aggregate()
и некоторые меры предосторожности, направленные на то, чтобы не удалять элементы «изображения» из массива и только не соответствующие «тегам».
В идеале это сделать с MongoDB 3.2, используя $filter
внутри $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"]
}
}
}
}}
])
или, возможно, с помощью $map
и $setDifference
, который также совместим с MongoDB 2.6, до тех пор, как «образы» содержание «уникальным» для каждая запись. Это происходит из-за «набор» операции, в которой «наборы» являются «уникальными»:
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]
]
}
}}
])
Это может быть сделано в более ранних версиях MongoDB, но, возможно, лучше избегать из-за стоимости обработки $unwind
на массив:
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" }
}}
])
Поскольку, как правило, значительные затраты при использовании $unwind
для этой цели, когда вы не «агрегирование» ничего, а затем, если у вас нет современной версии, где другие практические подходы доступны, это часто лучше всего принимать «фильтрацию» содержимого массива в клиентском коде, а не на сервере.
Таким образом, вы должны использовать только $unwind
для этого случая, когда записи массива будут «значительно» уменьшены по порядку удаления несоответствующих элементов. В противном случае стоимость обработки, вероятно, будет больше, чем стоимость передачи данных по сети, и любая польза будет отменена.
Если у вас нет современной версии, тогда получите ее. Эти особенности имеют значение для практического и практичного.
Ваше элементовое совпадение, похоже, находится в секции проекта, а не в секции фильтра (но я могу ошибаться). Попробуйте: 'db.site_users.find ({'images.tags':" broken ", {images: {$ elemMatch: {'tags': 'broken'}}}, {images: 1}). Pretty()' ? –