Моя цель заключается в поиске записей данных ИД пользователя 1
Ниже мои данные
{ "_id" : 2,
"name" : "test",
"data" :[{"_id" : "1","file" : "nic", "userid" : [1,2 ]},
{"_id" : "2","file" : "nic1","userid" : [1 ] },
{"_id" : 3,"file" : "nick2","userid" : [1,2 ]}
]},
{ "_id" : 3,
"name" : "test",
"data" : [{"_id" : "1","file" : "nic","userid" : [1,2 ] },
{"_id" : "2","file" : "nic1", "userid" : [3,2 ] }
]}
выход положен
{ "_id" : 2,
"name" : "test",
"data" :[{"_id" : "1","file" : "nic", "userid" : [1,2 ]},
{"_id" : "2","file" : "nic1","userid" : [1 ] },
{"_id" : 3,"file" : "nick2","userid" : [1,2 ]}
]},
{ "_id" : 3,
"name" : "test",
"data" : [{"_id" : "1","file" : "nic","userid" : [1,2 ] },
]}
Я старался
$res=$collection->find(array("data.userid" =>array('$in'=>array('52'))));
возвращая ноль
Вам нужно .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
test проверяет, что внешний массив на самом деле имеет хотя бы один элемент и не является пустым в результате фильтрации.
Возвращаются документы с соответствующим условием и только те элементы массива, которые также соответствуют указанному условию.
Конечно, операторы здесь требуют, чтобы у вас был как минимум 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' )
)
)
))
Других решений пока нет …