聚合$ group $ sum字段在一个文档中

时间:2017-04-28 13:26:45

标签: mongodb aggregation-framework

以下是文档示例,年份字段包含年份密钥,其中包含一些包含天数作为键的指标:

{ 
"_id" : NumberInt(1), 
"year" : {
    "2017" : {
        "g1" : {
            "1" : {
                "total" : 2.0
            }, 
            "2" : {
                "total" : 5.0
            }
        }, 
        "g2" : {
            "1" : {
                "total" : 3.0
            }, 
            "2" : {
                "total" : 6.0
            }
        }
    }
}

我不希望将文档存入内存以总结每个关键字段g#的总字段。

我怎么能对mongodb说,为年份字段中的每个键汇总总字段。

我想要的结果:g1 = 7.0,g2 = 9.0

1 个答案:

答案 0 :(得分:1)

您必须将结构的year部分更改为以下内容。(首选)

"year" : [{ "k" : "2017", "v":[{ "k": "g1", "v":[{ "k" : "1","v" : {"total" : 2 }},{ "k" : "2","v" : {"total" : 5}}]}, { "k": "g2", "v":[{ "k" : "1","v" : {"total" : 3 }},{ "k" : "2","v" : {"total" : 6}}]}]}]

您可以进行以下聚合。这将在不事先知道密钥的情况下工作。

查询$unwinds几次到达g & total文档后跟g项上的组,并计算total总和。

db.collection.aggregate([
 {$match:{_id:1}},
 {$unwind:"$year"},
 {$unwind:"$year.v"},
 {$unwind:"$year.v.v"},
 {
  $group: 
    {
      _id:"$year.v.k",
      sum: {$sum:"$year.v.v.v.total"}   
    }
 }
 ])

如果您无法改变结构,这就是解决方案。

您可以使用3.4.4版本并使用$objectToArray将所有动态密钥转换为带标签的密钥和值对。

第1阶段& 2:匹配_id过滤器并将动态year密钥转换为标签值对。

第3阶段& 4:$ unwind year阵列&在将totalg1动态键更改为标记为键和值对之前,$减少g2值以计算总和。

db.collection.aggregate([
 {$match:{_id:1}},
 {$addFields: {"year": {$objectToArray: "$year"}}},
 {$unwind:"$year"},
 {
  $project: 
    {
      g1: 
        {
             $reduce: {
                input: {$objectToArray: "$year.v.g1"},
                initialValue: 0,
                in: { $sum: [ "$$value", "$$this.v.total" ] }
            }
        },
      g2: 
        {
             $reduce: {
                input: {$objectToArray: "$year.v.g2"},
                initialValue: 0,
                in: { $sum: [ "$$value", "$$this.v.total" ] }
            }
        }
    }
 }
])