MongoDB多级组

时间:2018-08-09 07:21:24

标签: mongodb aggregation-framework

我有一些输入数据:

Brand   | Model   | Number
Peugeot | 208     | 1
Peugeot | 4008    | 2
Renault | Clio    | 3
Renault | Megane  | 4

我想同时获得两者:

  • 每个品牌的总和

  • 总和

这是我的预期输出:

Brand   | Number
Peugeot | 3
Renault | 7
Total   | 10

我认为我必须创建两个$group操作,并将Total设置为$literal。 正确的方法是什么?

1 个答案:

答案 0 :(得分:1)

正如您所说,这可以通过2组bys来完成,所以让我们开始将一些数据输入到mongo中,类似于您的示例输入:

> db.cars.insertMany([
   { "Brand" : "Peugeot", "Model" : "208", "Number": 1 },
   { "Brand" : "Peugeot", "Model" : "4008", "Number": 2 },
   { "Brand" : "Renault", "Model" : "Clio", "Number": 3 },
   { "Brand" : "Renault", "Model" : "Megane", "Number": 4 }
 ]);

现在我们已经插入了所有汽车,然后可以使用2个组聚合运算符对这些汽车进行聚合:

db.cars.aggregate([
  { $group : { "_id" : "$Brand", "Number" : { $sum : "$Number" }}},
  { $group : { "_id" : null, "Rows" : { $push : { "Brand" : "$$ROOT._id", "Number" : "$Number" } }, "Total" : {$sum : "$Number" } }}

])

这将为我们提供以下输出

{
        "_id" : null,
        "Rows" : [
                {
                        "Brand" : "Renault",
                        "Number" : 7
                },
                {
                        "Brand" : "Peugeot",
                        "Number" : 3
                }
        ],
        "Total" : 10
}

然后我们可以用投影将其清理

db.cars.aggregate([
  { "$group" : { "_id" : "$Brand", "Number" : { $sum : "$Number" }}},
  { "$group" : { "_id" : null, "Rows" : { $push : { "Brand" : "$$ROOT._id", "Number" : "$Number" } }, "Total" : {$sum : "$Number" } } },
  { "$project" : { "_id" : 0, "Data" : { "$concatArrays" : [ "$Rows", [ { "Brand": { $literal : "Total" }, "Number" : "$Total" } ] ] } } }
])

给我们以下结果

{
        "Data" : [
                {
                        "Brand" : "Renault",
                        "Number" : 7
                },
                {
                        "Brand" : "Peugeot",
                        "Number" : 3
                },
                {
                        "Brand" : "Total",
                        "Number" : 10
                }
        ]
}