如何在MongoDB中用聚合查询计算数组元素的累计和?
如何在MongoDB聚合中计算数组内marks的累计和?
嘿,要计算你集合里每个学生result数组中marks的累计和,MongoDB的聚合框架里有几种实用的方法,我给你拆解一下:
方案一:通用版(适配所有支持聚合的MongoDB版本)
如果你的MongoDB版本比较旧,用$reduce配合$map就可以实现,它能遍历数组并逐步计算累计值,同时保留原数组的每个元素信息:
db.students.aggregate([ { $addFields: { resultWithCumulative: { $reduce: { input: "$result", initialValue: { cumulativeSum: 0, items: [] }, in: { cumulativeSum: { $add: ["$$value.cumulativeSum", "$$this.marks"] }, items: { $concatArrays: [ "$$value.items", [ { test: "$$this.test", marks: "$$this.marks", cumulativeMarks: { $add: ["$$value.cumulativeSum", "$$this.marks"] } } ] ] } } } } } }, { $project: { student: 1, result: "$resultWithCumulative.items" } } ])
步骤解释:
$addFields阶段:用$reduce遍历每个学生的result数组,初始化累计和为0、空数组存结果。每次迭代时,把当前元素的marks加到累计和上,再将包含原test、marks和当前累计值的对象存入结果数组。$project阶段:整理输出结构,把计算后的数组替换回原来的result字段。
方案二:简洁版(MongoDB 5.0+适用)
如果你的MongoDB是5.0及以上版本,$setWindowFields窗口函数会让这个操作更简洁,它专门用来处理这类序列累计计算:
db.students.aggregate([ { $unwind: "$result" }, { $setWindowFields: { partitionBy: "$_id", sortBy: { "result.test": 1 }, // 这里的排序规则要根据你的业务需求调整,确保累计顺序正确 output: { cumulativeMarks: { $sum: "$result.marks", window: { documents: ["unbounded", "current"] } } } } }, { $group: { _id: "$_id", student: { $first: "$student" }, result: { $push: { test: "$result.test", marks: "$result.marks", cumulativeMarks: "$cumulativeMarks" } } } } ])
步骤解释:
$unwind:先把result数组拆分成单个文档,这样窗口函数才能逐个处理元素。$setWindowFields:按学生的_id分组,按result.test排序(你可以换成其他字段,比如时间戳,只要符合你想要的累计顺序),然后计算从数组开头到当前元素的marks总和,作为cumulativeMarks。$group:把拆分后的文档重新聚合回原结构,将每个元素和对应的累计值组装成新的result数组。
额外需求:只需要学生的总累计分?
如果不需要每个测试的累计,只想要每个学生所有marks的总和,那更简单:
db.students.aggregate([ { $addFields: { totalCumulativeMarks: { $reduce: { input: "$result", initialValue: 0, in: { $add: ["$$value", "$$this.marks"] } } } } } ])
内容的提问来源于stack exchange,提问作者Purushotam Thakur
相关产品推荐
相关产品推荐

