Für die beste Leistung, die Sie tatsächlich .aggregate()
mit einer $match
Bühne für eine „Abfrage“ mögliche Übereinstimmungen zu den Dokumenten zu verengen, die $all
die Elemente in dem Array enthalten verwenden würden, und $redact
von den übrigen Ergebnissen filtern:
db.test.aggregate([
{ "$match": { "hobby": { "$all": [ "chess", "cards" ] } } },
{ "$redact": {
"$cond": {
"if": {
"$eq": [
{ "$filter": {
"input": "$hobby",
"as": "hobby",
"cond": {
"$or": [
{ "$eq": [ "$$hobby", "chess" ] },
{ "$eq": [ "$$hobby", "cards" ] }
]
}
}},
["chess","cards"]
]
},
"then": "$$KEEP",
"else": "$$PRUNE"
}
}}
])
der Grund, dass, weil $filter
funktioniert, ist nur die Elemente zurückgeben können, die die Bedingungen hier angegebenen übereinstimmen, und gibt sie „in derselben Reihenfolge“, in dem sie in dem Originaldokument gespeichert werden.
Once „gefiltert“ nach unten, sollte das Array dann eine genaue Übereinstimmung für den Inhalt ["chess","cards"]
, wenn in der Tat jener Elemente in der ursprünglichen Anordnung in dieser Reihenfolge waren.
Beachten Sie, dass, während es "einfacher" aussehen kann, Sie "set operators" nicht verwenden können, um dies zu testen, da "Sets" tatsächlich nicht als bestellt angesehen werden.
Sie brauchen also etwas, das die Reihenfolge aufrechterhält, und $filter
ist wirklich die einzige Sache, die dies mit Array-Inhalt in einer effizienten Weise tun kann. Die Lösung beschränkt sich in der Tat auf eine Version von MongoDB 3.2 oder höher, um tatsächlich zu funktionieren.
Für ältere Versionen finden Sie in die answer from JohnnyHK mit $where
zu verwenden $all
einen .indexOf()
Test auf den Array-Elementen als zusätzliche Filter anzuwenden.
Aber wenn Sie MongoDB 3.2 mit den verfügbaren Operatoren haben, dann laufen die systemeigenen codierten Operationen, die für das Aggregationsframework verfügbar sind, viel schneller als die JavaScript-Auswertung $where
und sollten bevorzugt verwendet werden.