我的目标是搜索数据记录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 ] }
]}
out put应该是
{ "_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'))));
返回null
答案 0 :(得分:1)
您需要使用.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作为服务器(现在这是一个相当旧的版本,至少是一个建议的更新),但如果你的版本较少,那么你需要一个传统的方法{ {3}}和$unwind
:
$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' )
)
)
))