Sie können nicht mehrere Elemente eines Arrays zurückgeben, die Ihren Kriterien in irgendeiner Form eines einfachen .find()
entsprechen Anfrage. Um mehr als ein Element abzugleichen, müssen Sie .aggregate()
verwenden Methode statt.
Der Hauptunterschied besteht hier darin, dass die "Abfrage" genau das tut, was sie tun soll, und "Dokumente" findet, die Ihren Bedingungen entsprechen. Sie können versuchen, den Positionscode $
zu verwenden -Operator innerhalb eines Projektionsarguments, aber die dortigen Regeln lauten, dass er nur mit dem "ersten" Array-Element übereinstimmt, das den Abfragebedingungen entspricht.
Um nach mehreren Array-Elementen zu "filtern", gehen Sie wie folgt vor:
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" }
}}
])
In modernen Versionen von MongoDB ab Version 2.6 können Sie dies mit $redact
tun :
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"
]
}}
])
Das ist wahrscheinlich Ihre effizienteste Option, aber es ist rekursiv, also betrachten Sie zuerst Ihre Dokumentstruktur, da das gleichnamige Feld auf keiner Ebene mit einer anderen Bedingung existieren kann.
Möglicherweise sicherer, aber nur nützlich, wenn die Ergebnisse im Array "wirklich eindeutig" sind, ist diese Technik mit $map
und $setDifference
:
db.sample.aggregate([
{ "$project": {
"filtermetric": { "$setDifference": [
{ "$map": [
"input": "$filtermetric",
"as": "el",
"in": {"$cond": [
{ "$eq": [ "$$el.class", "s2" ] },
"$$el",
false
]}
]},
[false]
]}
}}
])
Beachten Sie auch, dass sowohl in der $group
und $project
operative Pipeline-Phasen, die Sie benötigen um alle Felder anzugeben, die Sie ab diesem Zeitpunkt in Ihren Ergebnisdokumenten zurückgeben möchten.
Der letzte Hinweis ist, dass $elemMatch
ist nicht erforderlich, wenn Sie nur den Wert eines einzelnen Schlüssels innerhalb eines Arrays abfragen. Die Punktnotation wird bevorzugt und empfohlen, wenn nur auf einen einzelnen Schlüssel des Arrays zugegriffen wird. $elemMatch
sollte nur benötigt werden, wenn "mehrere" Schlüssel im Dokument innerhalb des Arrays "element" einer Abfragebedingung entsprechen müssen.