Mongodb 多嵌套数组搜索
我的目的是搜索数据userid 1的记录
My aim is to search records of data userid 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 并不关心数据在数组内,只要指定的路径是正确的:
You need the .aggregate()
method in order to "filter" any array content for more than a singular match, and also the basic match is a lot simplier as MongoDB does not care that the data is within arrays, just as long as the specified path is correct:
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 中,这表示如下:
With PHP this notates as follows:
$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
.
The $map
operator allows inspection of each element ofthe outer array and passed each element to the $cond
ternary operation. This processes a $setIsSubset
operation on the "inner" array to see if it in fact contains one of the values in the alternate set ( in this case [1]
) and where a true
evaluation is made then the element is returned or otherwise false
.
$setDifference
的要点 是从修改后的数组中删除那些 false
值,只返回匹配的元素.最后是 $exists
测试查看外部数组实际上至少有一个元素并且由于过滤而不是空的.
The point of $setDifference
is to remove those false
values from the modified array and only return matched elements. And finally the $exists
test looks to see that outer array actually has at least one element and is not empty as a result of the filtering.
返回的文档是符合条件的文档,并且只有数组元素也符合指定的条件.
The documents returned are the ones with the matching condition and only the array elements that also match the specified condition.
当然,这里的操作员要求您至少有 MongoDB 2.6 作为服务器(这是一个相当老的版本,至少是一个建议的更新)但是如果您仍然有一个较小的版本,那么您需要使用 $unwind
和 $group
:
Of course the operators here require that you have at least MongoDB 2.6 as the server ( which is quite an old release now and an advised update at least ) but if you still have a lesser version then you need a traditional approach with $unwind
and $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' )
)
)
))
相关文章