检查嵌入是否存在 - 聚合框架mongodb

时间:2014-12-16 17:07:48

标签: mongodb aggregation-framework

这是我的测试集:

>db.test.find()
{
    "_id": ObjectId("54906479e89cdf95f5fb2351"),
    "reports": [
        {
            "desc": "xxx",
            "order": {"$id": ObjectId("53fbede62827b89e4f86c12e")}
        }
    ]
},
{
    "_id": ObjectId("54906515e89cdf95f5fb2352"),
    "reports": [
        {
            "desc": "xxx"
        }
    ]
},
{
    "_id": ObjectId("549067d3e89cdf95f5fb2353"),
    "reports": [
        {
            "desc": "xxx"
        }
    ]
}

我想用订单统计所有文件和文件,所以:

>db.test.aggregate({
    $group: {
        _id: null,
        all: {
            $sum: 1
        },
        order: {
            $sum: {
                "$cond": [
                    {
                        "$ifNull": ["$reports.order", false]
                    },
                    1,
                    0
                ]
            }
        }
    }
})

和我的结果:

{
    "result" : [ 
        {
            "_id" : null,
            "all" : 3,
            "order" : 3
        }
    ],
    "ok" : 1
}

但预计:

{
    "result" : [ 
        {
            "_id" : null,
            "all" : 3,
            "order" : 1
        }
    ],
    "ok" : 1
}

我将放置的内容没有区别 - “$ reports.order”,“$ reports.xxx”等,只有当字段报告存在时才会检查聚合框架,忽略嵌入。 $ ifNull和$ eq dos不能用于嵌入文档吗? 有办法做这样的事吗

db.test.find({"reports.order": {$exists: 1}})

在聚合框架中? 对不起我的英语,我希望你明白我想给你看的东西:)

1 个答案:

答案 0 :(得分:0)

我认为它不起作用,因为该领域"报告"包含一个数组,而不是一个对象。

我的意思是,您的聚合在此集合中按预期工作:

>db.test.find() 
{
    "_id": ObjectId("54906479e89cdf95f5fb2351"),
    "reports":
        {
            "desc": "xxx",
            "order": {"$id": ObjectId("53fbede62827b89e4f86c12e")}
        }
},
{
    "_id": ObjectId("54906515e89cdf95f5fb2352"),
    "reports": 
        {
            "desc": "xxx"
        }

},
{
    "_id": ObjectId("549067d3e89cdf95f5fb2353"),
    "reports": 
        {
            "desc": "xxx"
        }

}

请注意,我删除了" ["和"]",所以现在它是一个对象,而不是一个数组(一对一的关系)。

因为你在"报告中有数组"在字段中,您需要展开数组以为每个元素输出一个文档。我想如果你有两个"命令" "报告"内的字段数组,你只想数一次。我的意思是:

 "reports": [
        {
            "desc": "xxx",
            "order": {"$id": ObjectId("53fbede62827b89e4f86c12e")},
            "order": "yyy",
        }
    ]

只应算作最终对象的一个​​" order"总和。

在这种情况下,您需要展开,按_id分组(因为前面的示例为同一个_id输出两个文档),然后再次分组以计算所有文档:

db.test.aggregate([
    {$unwind: '$reports'}, 
    {$group:{
        _id:"$_id",
        order:{$sum:{"$cond": [
                {
                    "$ifNull": ["$reports.order", false]
                },
                1,
                0
                ]
            }
        }
    }},
    {$group:{
        _id:null,
        all:{$sum:1},
        order: {
            $sum:{
                "$cond": [{$eq: ['$order', 0]}, 0, 1]
            }
        }
}}])

也许有一个更短的解决方案,但这可行。