Nie możesz zwrócić wielu elementów tablicy pasujących do twoich kryteriów w żadnej formie podstawowego .find()
zapytanie. Aby dopasować więcej niż jeden element, musisz użyć .aggregate()
zamiast tego.
Główną różnicą jest to, że „zapytanie” robi dokładnie to, do czego jest przeznaczone, i dopasowuje „dokumenty”, które spełniają Twoje warunki. Możesz spróbować użyć pozycyjnego $
operator w argumencie projekcji, ale istnieją zasady, że będzie on pasował tylko do „pierwszego” elementu tablicy, który pasuje do warunków zapytania.
Aby „przefiltrować” wiele elementów tablicy, wykonaj następujące czynności:
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" }
}}
])
W nowoczesnych wersjach MongoDB, które są w wersji 2.6 lub nowszej, możesz to zrobić za pomocą $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"
]
}}
])
Jest to prawdopodobnie najbardziej wydajna opcja, ale jest ona rekurencyjna, więc najpierw zastanów się nad strukturą dokumentu, ponieważ to samo nazwane pole nie może istnieć z żadnym innym warunkiem na żadnym poziomie.
Prawdopodobnie bezpieczniejsza, ale przydatna tylko wtedy, gdy wyniki w tablicy są „naprawdę unikalne” jest ta technika z $map
i $setDifference
:
db.sample.aggregate([
{ "$project": {
"filtermetric": { "$setDifference": [
{ "$map": [
"input": "$filtermetric",
"as": "el",
"in": {"$cond": [
{ "$eq": [ "$$el.class", "s2" ] },
"$$el",
false
]}
]},
[false]
]}
}}
])
Zauważając również, że w obu $group
i $project
operacyjne etapy rurociągu, których potrzebujesz aby określić wszystkie pola, które zamierzasz zwrócić w dokumentach wynikowych z tego etapu.
Ostatnia uwaga jest taka, że $elemMatch
nie jest wymagane, gdy pytasz tylko o wartość pojedynczego klucza w tablicy. „Notacja kropkowa” jest preferowana i zalecana w przypadku dostępu tylko do jednego klucza tablicy. $elemMatch
powinno być potrzebne tylko wtedy, gdy „wiele” kluczy w dokumencie w tablicy „element” musi pasować do warunku zapytania.