【问题标题】:MongoDB filter multi sub-documentsMongoDB过滤多个子文档
【发布时间】:2015-07-23 18:06:39
【问题描述】:

我在 mongo DB 中有一个类似这样结构的文档,我想过滤以仅显示活动的子文档:活动的汽车和活动的水果。

    {
       "name":"Andre",
       "fruits":[
           {
              "active":true,
              "fruitname":"apple" 
           },{
              "active":false,
              "fruitname":"banana" 
           }
       ],
       "cars":[
           {
               "active":false,
               "carname":"ford"
           },{
               "active":true,
               "carname":"GM"
           },
       ]
    }

这是我想要的结果。

    {
       "name":"Andre",
       "fruits":[
           {
              "active":true,
              "fruitname":"apple" 
           }
       ],
       "cars":[
          {
               "active":true,
               "carname":"GM"
           },
       ]
    }

我试过Aggregate,但是当任何汽车或任何水果活动时,它什么也没有返回。

    m_object.aggregate([
        { $match : {
           "name": "andre"
       }},
       { $unwind : "$fruits" },
       { $unwind : "$cars" },
       { $match : {
        'fruits.active':{$eq: true}
        }},
       { $match : {
        'cars.active':{$eq: true}
        }},

    { $group : {
       "name": "$name",
       cars: { $addToSet : "$cars" }
       fruits: { $addToSet : "$fruits" }
    }}
    ], function (err, result) {
        if (err) {
            console.log(err);
            return;
        }
        console.log('result');
    });

有没有办法在那些子文档中省略"active":false 子文档?

【问题讨论】:

    标签: json node.js mongodb mongoose subdocument


    【解决方案1】:

    使用以下聚合管道获得所需的结果:

    var pipeline = [
        {
            "$match": {
                "name": "Andre",
                "fruits.active": true,
                "cars.active": true
            }
        },
        { "$unwind": "$fruits" },
        { "$unwind": "$cars" },
        {
            "$match": {            
                "fruits.active": true,
                "cars.active": true
            }
        },
        { 
            "$group": {
                "_id": {
                    "_id": "$_id",
                    "name": "$name"
                },
                "cars": { "$addToSet" : "$cars" },
                "fruits": { "$addToSet" : "$fruits" }
            }
        },
        {
            "$project": {
                "_id": 0,
                "name": "$_id.name",
                "cars": 1,
                "fruits": 1
            }
        }    
    ]
    
    m_object.aggregate(pipeline)
            .exec(function (err, result) {
                if (err) {
                    console.log(err);
                    return;
                }
                console.log('result');
            });
    

    或者您可以使用 aggregation pipeline 构建器,如下所示:

    m_object.aggregate()
            .match({
                "name": "Andre",
                "fruits.active": true,
                "cars.active": true
             })
            .unwind("fruits")
            .unwind("cars")
            .match({
                "fruits.active": true,
                "cars.active": true
             })
            .group({
                "_id": {
                    "_id": "$_id",
                    "name": "$name"
                },
                "cars": { "$addToSet" : "$cars" },
                "fruits": { "$addToSet" : "$fruits" }
            })
            .project({
                "_id": 0,
                "name": "$_id.name",
                "cars": 1,
                "fruits": 1
            })
            .exec(callback);
    

    【讨论】:

    • 它有效,但是如果所有汽车都是active: false,则根本没有返回任何[ ]。有什么方法可以使用此解决方案,如果所有汽车都被禁用,请获取 [{"name":andre", fruits[{..},{..}], "cars":[]}] 而不是 []
    • @AndreTorbitoni 以你的方式改变你的问题真的不是一个好主意。对于那些过来发现提供的答案与您所要求的不符的人来说,这是非常具有误导性的。如果您发布另一个问题,我将与其他人一样乐意回答。这里的一般情况是一问一答。我可以回答您的其他问题,但这应该完全是另一个问题。请单独发布。
    • 对不起,我已经为此写了另一个问题。 stackoverflow.com/questions/30199798/…
    猜你喜欢
    • 2015-08-26
    • 1970-01-01
    • 2014-09-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-26
    相关资源
    最近更新 更多