MongoDB如何通过键数组(非值)进行过滤?

时间:2016-02-26 12:45:41

标签: mongodb mongodb-query aggregation-framework mongodb-php

我有一个带用户密钥的数组。

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。

2 个答案:

答案 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)