是否可以从MongoDB返回嵌入文档数组的指定子集

时间:2015-02-10 08:46:44

标签: mongodb

对于嵌入式文档的查询,我希望返回匹配元素,以及预先指定的元素集。例如,使用

说我有一个如下的集合:

{_id: 1,
 data:[
    {who: 'Alice',  score: 20},
    {who: 'Brad',  score: 25},
    {who: 'Charlie',  score: 30},
    {who: 'Dave',  score: 40},
    {who: 'Elaine',  score: 50},
    {who: 'Frank',  score: 20}   

 ]},
 {_id: 2,
 data:[
    {who: 'Alice',  score: 30},
    {who: 'Brad',  score: 50},
    {who: 'Charlie',  score: 68},
    {who: 'Dave',  score: 20},
    {who: 'Elaine',  score: 50},
    {who: 'Frank',  score: 20}   

 ]},
   ...

如果我需要总是返回Alice和Brad,以及得分等于50的任何人,我倾向于使用

find({data.score: 50}, {'data.who': {'$in': ['Alice', 'Brad', '$']}})
or 
aggregate([{'$match': {data.score: 50}}, 
           {'$project': {'data': 1}},
           {'$unwind': '$data'}, 
           {'$match': {'data.who': {'$in': ['Alice', 'Brad', '$']}}}])

不幸的是,两者都不起作用。

实现它的正确方法是什么,甚至是可能的?

2 个答案:

答案 0 :(得分:1)

您可以使用$redact阶段汇总结果。这消除了$unwind阶段的需要,在大数据集的情况下,这可能会被证明是安静的。

  • 使用$redact阶段运算符,$$PRUNE子文档 不符合$cond表达式中的条件。

代码:

 db.t.aggregate([
 {$redact:{$cond:[{$or:[{$eq:[{$ifNull:["$who","Alice"]},"Alice"]},
                        {$eq:[{$ifNull:["$who","Brad"]},"Brad"]},
                        {$eq:[{$ifNull:["$score",50]},50]}
                       ]},"$$DESCEND","$$PRUNE"]}}
 ])

或者您可以对现有代码稍作修改,如下所示:

  • $match条件应包含所有三个条件 保留一份子文件。

  • 然后$unwind

  • 然后再次应用相同的$match条件以选择未缠绕的条件 文档。

  • {li>

    $group _id合并所选的数据子文档 每个_id

代码:

db.t.aggregate([
 {$match:{$or:[{"data.who":{$in:["Alice","Brad"]}},
               {"data.score":{$eq:50}}]}},
 {$unwind:"$data"},
 {$match:{$or:[{"data.who":{$in:["Alice","Brad"]}},
               {"data.score":{$eq:50}}]}},
 {$group:{"_id":"$_id","data":{$push:"$data"}}}
 ])

O / P:

{
        "_id" : 1,
        "data" : [
                {
                        "who" : "Alice",
                        "score" : 20
                },
                {
                        "who" : "Brad",
                        "score" : 25
                },
                {
                        "who" : "Elaine",
                        "score" : 50
                }
        ]
}
{
        "_id" : 2,
        "data" : [
                {
                        "who" : "Alice",
                        "score" : 30
                },
                {
                        "who" : "Brad",
                        "score" : 50
                },
                {
                        "who" : "Elaine",
                        "score" : 50
                }
        ]
}

答案 1 :(得分:0)

我认为根据我的理解,以下查询将符合您的标准

db.collectionName.aggregate({
    "$unwind": "$data"
},
{
    "$match": {
    "$or": [
        {
            "data.score": 50
        },
        {
            "data.who": "Alice"
        },
        {
            "data.who": "Brad"
        }
    ]
    }
},
{
    "$project": {
    "_id": 0,
    "data": "$data"
    }
}).pretty()