嵌套查询Mongodb

时间:2014-04-07 17:37:58

标签: mongodb

我有这个漂亮的Json,我正在尝试使用强大的mongodb查询来获取file_id 12的所有注释....所以这就是我想要的[4,5,7,10,11, 15]。

我试过这个查询但是file_id被引擎完全忽略了:

db.collection.distinct("changes.comments",
        {"my_uuid":"bf48e757-1a65-4546-bf24-2bb001effddd",
         "changes":{$elemMatch:{file_id:12}} } 
)

输出:

{
    "_id" : ObjectId("5342bf796b03d7ffc834afcc"),
    "my_uuid" : "bf48e757-1a65-4546-bf24-2bb001effddd",
    "changes" : [ 
        {
            "file_id" : 12,
            "version" : 1,
            "comments" : [ 
                4, 
                5, 
                7
            ],
            "lastseen" : 1394640549
        }, 
        {
            "file_id" : 12,
            "version" : 2,
            "comments" : [ 
                10, 
                11, 
                15
            ],
            "lastseen" : 1394640511
        }, 
        {
            "file_id" : 234,
            "version" : 1,
            "comments" : [ 
                100, 
                110, 
                150
            ],
            "lastseen" : 1394640555
        }
    ]
}

提前致谢

2 个答案:

答案 0 :(得分:2)

您可以使用aggregation framework来实现您的目标。尽管查询对于您要执行的操作看起来很复杂,但只要您了解它就很简单。

db.collection.aggregate([
    // Get only documents where "my_uuid" equals "bf48e757-1a65-4546-bf24-2bb001effddd"
    {"$match":{"my_uuid":"bf48e757-1a65-4546-bf24-2bb001effddd"}},
    // Unwind the "changes" array
    {"$unwind":"$changes"},
    // Get only elements of the "changes" array where "file_id" equals 12
    {"$match":{"changes.file_id":12}},
    // Unwind the "comments" array
    {"$unwind":"$changes.comments"},   
    // Group by _id and add the comments to array only if not already present
    {"$group":{_id:"$_id", comments:{$addToSet:"$changes.comments"}}},
    // Cleanup the output
    {"$project":{_id:0, comments:1}}
])

输出:

{
        "result" : [
                {
                        "comments" : [
                                4,
                                5,
                                7,
                                10,
                                11,
                                15
                        ]
                }
        ],
        "ok" : 1
}

编辑:在结果中包含my_uuid非常简单。我们只需要按my_uuid而不是_id进行分组:

db.collection.aggregate([
    {"$match":{"my_uuid":"bf48e757-1a65-4546-bf24-2bb001effddd"}},
    {"$unwind":"$changes"},
    {"$match":{"changes.file_id":12}},
    {"$unwind":"$changes.comments"},   
    {"$group":{_id:"$my_uuid", comments:{$addToSet:"$changes.comments"}}},
    {"$project":{_id:0, my_uuid:"$_id", comments:1}}
])

答案 1 :(得分:0)

目前还没有直接从数组中提取匹配文档的方法。 $ elemMatch运算符仅确保阵列中的至少一个文档满足您提供的条件。但是,查询将始终返回整个文档。实现目标的一种方法是 -

db.sample4.aggregate({$unwind:"$changes"},{$match:{"changes.file_id":12}},{$project:{"changes.comments":1,"_id":0}});

这些主题在stackoverflow中涵盖here,其中列出了map-reduce方法以实现此目的。如果要求是返回第一个匹配的文档,那么您可以使用changes.comments.$:1 Eg进行投影。 - db.sample4.find({"changes":{$elemMatch:{"file_id":12}} },{"changes.comments.$":1} )