Ответ 1
Вы не можете вернуть несколько элементов массива, соответствующих вашим критериям, в любом виде базового запроса .find()
. Чтобы сопоставить более одного элемента, вам нужно использовать .aggregate()
.
Основное отличие здесь в том, что "запрос" делает именно то, что он предназначен, и сопоставляет "документы", соответствующие вашим условиям. Вы можете попытаться использовать оператор positional $
в аргументе проектирования, но есть правила, что он будет соответствовать только "первому" массиву который соответствует условиям запроса.
Чтобы "фильтровать" для нескольких элементов массива, действуйте следующим образом:
db.sample.aggregate([
// Filter possible documents
{ "$match": { "filtermetric.class": "s2" } },
// Unwind the array to denormalize
{ "$unwind": "$filtermetric" },
// Match specific array elements
{ "$match": { "filtermetric.class": "s2" } },
// Group back to array form
{ "$group": {
"_id": "$_id",
"filtermetric": { "$push": "$filtermetric" }
}}
])
В современных версиях MongoDB версии 2.6 или выше вы можете сделать это с помощью $redact
:
db.sample.aggregate([
// Filter possible documents
{ "$match": { "filtermetric.class": "s2" } },
// Redact the entries that do not match
{ "$redact": {
"$cond": [
{ "$eq": [ { "$ifNull": [ "$class", "s2" ] }, "s2" ] },
"$$DESCEND",
"$$PRUNE"
]
}}
])
Это, вероятно, самый эффективный вариант, но он рекурсивный, поэтому сначала рассмотрите структуру документа, так как одно и то же имя не может существовать ни с каким другим условием на любом уровне.
Возможно, более безопасный, но полезный, когда результаты в массиве "поистине уникальны" - это этот метод с $map
и $setDifference
:
db.sample.aggregate([
{ "$project": {
"filtermetric": { "$setDifference": [
{ "$map": [
"input": "$filtermetric",
"as": "el",
"in": {"$cond": [
{ "$eq": [ "$$el.class", "s2" ] },
"$$el",
false
]}
]},
[false]
]}
}}
])
Также отмечая, что в $group
и $project
рабочие этапы конвейера вам нужно, чтобы указать все поля, которые вы собираетесь возвращать в своих результирующих документах с этого этапа. p >
Последнее замечание: $elemMatch
не требуется, когда вы запрашиваете только одно значение ключ внутри массива. "Точечная нотация" является предпочтительным и рекомендуется при доступе только к одному ключу массива. $elemMatch
должен быть необходим только тогда, когда "несколько" ключей в документе внутри элемента "array" массива должны соответствовать условию запроса.