问题
If I have a collection like this:
{
"store" : "XYZ",
"total" : 100
},
{
"store" : "XYZ",
"total" : 200
},
{
"store" : "ABC",
"total" : 300
},
{
"store" : "ABC",
"total" : 400
}
I can get the $sum of orders in the collection by aggregation:
db.invoices.aggregate([{$group: { _id: null, total: { $sum: "$total"}}}])
{
"result": [{
"_id": null,
"total": 1000
}
],
"ok": 1
}
And I can get the $sum of orders grouped by store:
db.invoices.aggregate([{$group: { _id: "$store", total: { $sum: "$total"}}}])
{
"result": [{
"_id": "ABC",
"total": 700
}, {
"_id": "XYZ",
"total": 300
}
],
"ok": 1
}
But how can I do this in one query?
回答1:
You could aggregate as below:
$groupby thestorefield, calculate thesubtotal.$projecta fielddocto keep thesubtotalgroup in tact, during the next group.$groupbynulland accumulate the net total.
Code:
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
}
}
])
Output:
{
"total": 1000,
"result": [{
"_id": "ABC",
"total": 700
}, {
"_id": "XYZ",
"total": 300
}
]
}
回答2:
Another approach would be using the $facet aggregation stage.
$facetallows you to do multiple nested sub-aggregations within your main aggregation.- Each sub-aggregation has its own pipeline.
- For each result of a sub-aggregation we define another field.
Like this, for example:
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 wrote, that an
$unwindstage might be costly. However we're unwinding an array of length 1 here. So I'm curious which approach is more efficient under which circumstances. If someone can compare those withconsole.time(), I'd be happy to include the results.
Output
Should be the same as in the accepted answer.
来源:https://stackoverflow.com/questions/28420631/combine-multiple-groups-in-an-aggregation-in-mongodb