Mongodb поиск нескольких вложенных массивов

Моя цель заключается в поиске записей данных ИД пользователя 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'))));

возвращая ноль

3

Решение

Вам нужно .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' )
)
)
))
1

Другие решения

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector