Você precisa do
.aggregate()
método para "filtrar" qualquer conteúdo de array para mais de uma correspondência singular, e também a correspondência básica é muito mais simples, pois o MongoDB não se importa que os dados estejam dentro de arrays, desde que o caminho especificado esteja correto: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 } }}
])
Com o PHP isso nota o seguinte:
$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 ) ) )
))
O
$map
operador permite a inspeção de cada elemento da matriz externa e passa cada elemento para o $cond
operação ternária. Isso processa um $setIsSubset
operação no array "interno" para ver se ele de fato contém um dos valores no conjunto alternativo (neste caso [1]
) e onde um true
avaliação é feita então o elemento é retornado ou então false
. O ponto de
$setDifference
é remover aqueles false
valores da matriz modificada e retornam apenas os elementos correspondentes. E, finalmente, o $exists
test verifica se a matriz externa realmente tem pelo menos um elemento e não está vazia como resultado da filtragem. Os documentos retornados são aqueles com a condição correspondente e apenas os elementos da matriz que também correspondem à condição especificada.
É claro que os operadores aqui exigem que você tenha pelo menos o MongoDB 2.6 como servidor (que é uma versão bastante antiga agora e uma atualização recomendada pelo menos), mas se você ainda tiver uma versão menor, precisará de uma abordagem tradicional com
$unwind
e $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' )
)
)
))