我有一个带用户密钥的数组。
ID为:array的用户(' 111',' 333');
我会得到以下方案,只有一些具有这些ID的用户的字段(名称)。
{
"_id" : "78787878",
"users" : {
"111" : {
"name" : "William",
"e" : "w@sas..."
...
},
"222" : {
"name" : "Sarah",
"e" : "s@sas..."
},
"333" : {
"name" : "Marie",
"e" : "m@sas..."
},..
},..
}
我的预期结果是这样的:
{
"_id" : "78787878",
"users" : {
"111" : {
"name" : "William",
},
"333" : {
"name" : "Marie",
}
}
}
我尝试过:
db.getCollection('instagram').find({'_id' : '78787878', 'users' : { '$in' : ['456726', '2945551665'] } }, { '_id' : 0, 'users.name' : 1 })
如何进行此类查询?我可以用#34; findOne"或者应该与"聚合"?
根据评论,如果我修改架构如下:
{
"_id" : "78787878",
"users" : [
{
"id": 111,
"name" : "William",
"e" : "w@sas..."
...
},
{
"id": 222,
"name" : "Sarah",
"e" : "s@sas..."
},
{
"id": 333,
"name" : "Marie",
"e" : "m@sas..."
},..
]
}
如果我使用 $ in ,则会全部返回...为什么不应用过滤器?
$filter = array(111, 333);
$this->db->{$collection}->find(array('_id' => '78787878', 'users.id' => array('$in' => $filter)), array('users' => 1));
users.id是Int32。
答案 0 :(得分:1)
您可能希望重新构建数据,例如
{
"_id" : "78787878",
"users" : [
{
"id": "111",
"name" : "William",
"e" : "w@sas..."
...
},
{
"id": "222",
"name" : "Sarah",
"e" : "s@sas..."
},
{
"id": "333",
"name" : "Marie",
"e" : "m@sas..."
},..
]
}
然后你可以像
一样轻松查询db.instagram.find({'users.id':{$in: ['111', '333']}})
答案 1 :(得分:0)
使用这种模式,你有哈希键,除非你可以更改它以便用户id嵌入到数组中,否则查询将非常困难。
然而,有了这样的结构,唯一可用的选择是通过投影来获得所需的输出。您需要一种机制来构建投影,如以下查询
db.instagram.find(
{ "_id": "78787878"},
{ "users.111": 1, "users.333": 1 }
);
这将产生想要的输出
{
"_id" : "78787878",
"users" : {
"111" : {
"name" : "William",
"e" : "w@sas..."
},
"333" : {
"name" : "Marie",
"e" : "m@sas..."
}
}
}
因此,如果输入数组包含您只想投影的用户ID,则可以通过JavaScript的 Array.reduce()
函数构建投影文档,从而将数组缩减为宾语。
请考虑以下方法来创建上述查询:
var userIds = ['111', '333'],
query = { "_id": "78787878"},
projection = userIds.reduce(function(o, v, i) {
o["users."+v] = 1;
return o;
}, {});
db.instagram.find(query, projection)