Имате нужда от .aggregate()
метод, за да "филтрира" всяко съдържание на масив за повече от едно съвпадение, а също и основното съвпадение е много по-просто, тъй като MongoDB не се интересува, че данните са в масиви, стига посоченият път да е правилен:
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 } }}
])
С PHP това отбелязва следното:
$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 ) ) )
))
$map
операторът позволява проверка на всеки елемент от външния масив и предава всеки елемент на $cond
троична операция. Това обработва $setIsSubset
операция върху "вътрешния" масив, за да видите дали той всъщност съдържа една от стойностите в алтернативния набор ( в този случай [1]
) и където true
прави се оценка, след което елементът се връща или в противен случай false
.
Точката на $setDifference
е да премахнете тези false
стойности от модифицирания масив и връща само съответстващи елементи. И накрая $exists
тестът проверява дали външният масив действително има поне един елемент и не е празен в резултат на филтрирането.
Върнатите документи са тези със съответстващото условие и само елементите на масива, които също отговарят на определеното условие.
Разбира се, операторите тук изискват да имате поне MongoDB 2.6 като сървър (което вече е доста стара версия и поне препоръчителна актуализация), но ако все още имате по-малка версия, тогава ви трябва традиционен подход с $unwind
и $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' )
)
)
))