MongoDB 聚合中的总计

grand total in MongoDB aggregation

我有一个对象数组,需要在管道输出的字段中包含值的总计。

[
  {
    "_id": NumberInt(1),
    "absences": 170.0,
    "dayNumber": NumberInt(1),
    "dayName": "Sunday"
  },
  {
    "_id": NumberInt(2),
    "absences": 130.0,
    "dayNumber": NumberInt(2),
    "dayName": "Monday"
  }
]

我想要的结果包括 totalAbsences 键,它总结了所有文档中的缺席。

[
  {
    "_id": 1,
    "absences": 170,
    "dayName": "Sunday",
    "dayNumber": 1,
    "totalAbsences": 300
  },
  {
    "_id": 2,
    "absences": 130,
    "dayName": "Monday",
    "dayNumber": 2,
    "totalAbsences": 300
  }
]

我可以get the grand total with the code below, but I lose all other values in the pipeline. How can I add totalAbsences to every document and preserve what's already in the pipeline? This Mongo Playground模拟数据。

{
    _id: null,
        total: { 
            $sum: "$absences" 
        } 
}
db.collection.aggregate([
  {
    $group: {
      _id: null,
      total: {
        $sum: "$absences"
      },
      items: {
        $push: "$$ROOT"
      }
    }
  },
  {
    $unwind: "$items"
  },
  {
    $replaceRoot: {
      "newRoot": {
        $mergeObjects: [
          {
            total: "$total"
          },
          "$items"
        ]
      }
    }
  }
])

mongoplayground

您可以使用 $first$$ROOT 来保存文档。

{
  _id: '$orgId',
  total: {
    $sum: '$createdAt'
  },
  "doc": { "$first": "$$ROOT" }
}

之后您可以使用 $replaceRoot$mergeObjects

{
  newRoot: { $mergeObjects : [{ total: '$total' }, '$doc']}
}

在 MongoDB 5.0 版中,您可以使用新的 $setWindowFields(),它更简单,而且很可能也更快:

db.collection.aggregate([
  {
    $setWindowFields: {
      output: {
        totalAbsences: { $sum: "$absences" }
      }
    }
  }
])