Sie benötigen den .aggregate()
-Methode, um Array-Inhalte nach mehr als einer einzelnen Übereinstimmung zu "filtern", und auch die grundlegende Übereinstimmung ist viel einfacher, da MongoDB sich nicht darum kümmert, dass sich die Daten innerhalb von Arrays befinden, solange der angegebene Pfad korrekt ist:
db.collection.aggregate([
{ "$match": { "data.userid": 1 } },
{ "$project": {
"data": {
"$setDifference": [
{ "$map": {
"input": "$data",
"as": "el",
"in": {
"$cond": [
{ "$setIsSubset": [ [1], "$$el.userid" ] },
"$$el",
false
]
}
}},
[false]
]
}
}},
{ "$match": { "data.0": { "$exists": true } }}
])
Bei PHP wird dies wie folgt notiert:
$collection->aggregate(array(
array( '$match' => array( "data.userid" => 1 )),
array(
'$project' => array(
'data' => array(
'$setDifference' => array(
array(
'$map' => array(
'input' => '$data',
'as' => 'el',
'in' => array(
'$cond' => array(
array( '$setIsSubset' => array(array(1),'$$el.userid') ),
'$$el',
FALSE
)
)
)
),
array(FALSE)
)
)
)
),
array( '$match' => array( 'data.0' => array( '$exists' => TRUE ) ) )
))
Der $map
Operator ermöglicht die Untersuchung jedes Elements des äußeren Arrays und übergibt jedes Element an $cond
ternärer Betrieb. Dadurch wird ein $setIsSubset
verarbeitet
Operation auf dem "inneren" Array, um zu sehen, ob es tatsächlich einen der Werte in der alternativen Menge enthält (in diesem Fall [1]
) und wo ein true
Auswertung erfolgt, dann wird das Element zurückgegeben oder andernfalls false
.
Der Sinn von $setDifference
ist, diese false
zu entfernen Werte aus dem geänderten Array und geben nur übereinstimmende Elemente zurück. Und schließlich der $exists
test prüft, ob das äußere Array tatsächlich mindestens ein Element enthält und als Ergebnis der Filterung nicht leer ist.
Die zurückgegebenen Dokumente sind diejenigen mit der übereinstimmenden Bedingung und nur die Array-Elemente, die auch der angegebenen Bedingung entsprechen.
Natürlich verlangen die Operatoren hier, dass Sie mindestens MongoDB 2.6 als Server haben (das ist jetzt eine ziemlich alte Version und zumindest ein empfohlenes Update), aber wenn Sie noch eine niedrigere Version haben, dann brauchen Sie einen traditionellen Ansatz mit $unwind
und $group
:
$collection->aggregate(array(
array( '$match' => array( "data.userid" => 1 )),
array( '$unwind' => '$data' ),
array( '$match' => array( 'data.userid' => 1 )),
array(
'$group' => array(
'_id' => '$_id',
'data' => array( '$push' => '$data' )
)
)
))