Mongodb:Aggregation:在$ group之前对数组中的值求和

时间:2015-08-05 11:53:57

标签: mongodb mongodb-query aggregation-framework

我有一系列具有以下结构的文件:

{
    _id: 1,
    array: [
        {value: 10 },
        {value: 11 },
        {value: 12 }
    ]
}

我想对集合进行汇总查询: 得到每个项目的比例。 (即例如项目1的比例为项目1的value除以所有三项的值的总和。

注意: 我想在一次查询中执行此操作。

2 个答案:

答案 0 :(得分:5)

这里的基本思想是$unwind数组,$group文档,然后应用于每个数组成员。由于$map运算符,这对MongoDB 2.6或更高版本更有效:

db.collection.aggregate([
    { "$unwind": "$array" },
    { "$group": {
       "_id": "$_id",
       "array": { "$push": "$array" },
       "total": { "$sum": "$array.value" }
    }},
    { "$project": {
        "array": {
            "$map": {
                "input": "$array",
                "as": "el",
                "in": {
                    "value": "$$el.value",
                    "prop": { 
                        "$divide": [ "$$el.value", "$total" ]
                    }
                }
            }
        }
    }}
])

或者使用早期版本:

db.collection.aggregate([
    { "$unwind": "$array" },
    { "$group": {
       "_id": "$_id",
       "array": { "$push": "$array" },
       "total": { "$sum": "$array.value" }
    }},
    { "$unwind": "$array" },
    { "$group": {
        "_id": "$_id",
        "array": {
            "$push": {
                "value": "$array.value",
                "prop": {
                    "$divide": [ "$array.value", "$total" ]
                }
            }
        }
    }}
])

在任何一种情况下,如果你实际上并没有"汇总"除了文档之外的任何东西,在客户端代码中进行此计算要高效得多。由于它的作用,$unwind在这里会变得非常昂贵。

此外,如果您只是存储"总计"作为另一个元素,那么简单的 $project 就是您所需要的,而且本身成本非常低。保持更新总数只是简单地使用$inc运算符作为$push数组的新元素。

答案 1 :(得分:1)

以下是您需要的聚合管道:

[
    {$unwind: '$array'},
    {
        $group: {
            _id: '$_id', 
            array: {$push: '$array'}, 
            sum: {$sum: '$array.value'}
        }
    }, 
    {$unwind: '$array'},
    {
        $project: {
            _id: 1,
           'array.value': 1, 
           'array.proportion': {
               $divide: ['$array.value', '$sum']
           }
        }
    }
]