在mongodb中的聚合中组合多个组

时间:2015-02-09 22:26:31

标签: mongodb aggregation-framework

如果我有这样的集合:

{
    "store" : "XYZ",
    "total" : 100
},
{
    "store" : "XYZ",
    "total" : 200
},
{
    "store" : "ABC",
    "total" : 300
},
{
    "store" : "ABC",
    "total" : 400
}

我可以通过聚合获得集合中的$sum个订单:

db.invoices.aggregate([{$group: { _id: null, total: { $sum: "$total"}}}])

{
    "result": [{
            "_id": null,
            "total": 1000
        }
    ],
    "ok": 1
}

我可以获得按商店分组的$sum个订单:

db.invoices.aggregate([{$group: { _id: "$store", total: { $sum: "$total"}}}])

{
    "result": [{
            "_id": "ABC",
            "total": 700
        }, {
            "_id": "XYZ",
            "total": 300
        }
    ],
    "ok": 1
}

但是如何在一个查询中执行此操作?

2 个答案:

答案 0 :(得分:11)

您可以汇总如下:

    $group字段
  • store,计算subtotal

  • $project字段doc以确保subtotal群在下一个 基。

  • $group null并累计净总额。

<强>代码:

db.invoices.aggregate([{
            $group: {
                "_id": "$store",
                "subtotal": {
                    $sum: "$total"
                }
            }
        }, {
            $project: {
                "doc": {
                    "_id": "$_id",
                    "total": "$subtotal"
                }
            }
        }, {
            $group: {
                "_id": null,
                "total": {
                    $sum: "$doc.total"
                },
                "result": {
                    $push: "$doc"
                }
            }
        }, {
            $project: {
                "result": 1,
                "_id": 0,
                "total": 1
            }
        }
    ])

<强>输出:

{
    "total": 1000,
    "result": [{
            "_id": "ABC",
            "total": 700
        }, {
            "_id": "XYZ",
            "total": 300
        }
    ]
}

答案 1 :(得分:0)

另一种方法是使用$facet聚合阶段。

  • $facet允许您执行多个嵌套的 子聚合 在您的主要集合中。
  • 每个 子聚合 都有其自己的管道。
  • 对于 子聚合 的每个结果,我们定义另一个字段。

例如,

db.invoices.aggregate([
    {
        $facet: {
            total: [
                {
                    $group: {
                        _id: null,
                        total: { $sum: "$total"}
                    }
                }
            ],
            store_totals: [
                {
                    $group: {
                        _id: "$store",
                        total: { $sum: "$total"}
                    }
                }
            ]
        }
    },{
        $unwind: "$total"
    },{
        $project: {
            _id: 0,
            total: "$total.total",
            store_totals: "$store_totals"
        }
    }
]
  

@BatScream写道,$unwind阶段可能会很昂贵。然而   我们在这里展开长度为1的数组。所以我很好奇   在这种情况下,这种方法更有效。如果有人可以   与console.time()进行比较,我很乐意将   结果。


输出

  

应该与接受的答案相同。