MongoDB嵌套Map聚合求和数组元素失效,求保留原文档的解法
问题:MongoDB嵌套数组求和(保留原文档结构)
原始数据
[ { "result": { "events": [ { "amount": [ [ 1623224700000, "33333333" ], [ 1623224760000, "33333333" ], [ 1623224820000, "33333334" ] ] } ] } } ]
需求说明
需要对amount数组中每个子数组的第二个元素(字符串类型数值)求和,且要求保留原文档结构,仅新增求和字段。
错误的聚合管道
db.collection.aggregate([ { $addFields: { "amount_sum": { $sum: { $map: { input: "$result.events", as: "events", in: { $map: { input: "$events", as: "event", in: { $toInt: { $last: "$event.amount" } } } } } } } } } ])
错误输出结果
[ { "_id": ObjectId("5a934e000102030405000000"), "amount_sum": 0, "result": { "events": [ { "amount": [ [ 1.6232247e+12, "33333333" ], [ 1.62322476e+12, "33333333" ], [ 1.62322482e+12, "33333334" ] ] } ] } } ]
可用但不符合结构要求的管道($unwind方式)
该方式能得到正确求和结果,但会改变原文档结构:
db.collection.aggregate([ { $unwind: "$result.events" }, { $unwind: "$result.events.amount" }, { $addFields: { amount_sum: { $sum: { $toInt: { $last: "$result.events.amount" } } } } }, { $group: { _id: { id: "$_id" }, sum_amount: { $sum: "$amount_sum" } } } ])
对应输出结果
[ { "_id": { "id": ObjectId("5a934e000102030405000000") }, "sum_amount": 100000000 } ]
问题原因及解决方案
错误原因
- 变量引用错误:内层
$map使用$events引用外层变量,正确的引用方式应为$$events(MongoDB聚合中,$引用字段路径,$$引用自定义变量)。 - 遍历对象而非数组:内层
$map的input设为$$events(即单个event对象),但实际需要遍历的是$$events.amount数组。 - 二维数组无法直接求和:即使修正前两点,嵌套
$map会返回二维数组,$sum无法直接对二维数组求和,需先展平为一维数组。
正确管道(两种实现方式)
方式1:$map + $flatten
db.collection.aggregate([ { $addFields: { "amount_sum": { $sum: { // 展平二维数组为一维 $flatten: { $map: { input: "$result.events", as: "event", in: { // 遍历每个event的amount数组,取出数值并转整数 $map: { input: "$$event.amount", as: "item", in: { $toInt: { $last: "$$item" } } } } } } } } } } ])
方式2:$reduce + $concatArrays
db.collection.aggregate([ { $addFields: { "amount_sum": { $sum: { $reduce: { input: "$result.events", initialValue: [], in: { // 拼接每个event处理后的数值数组 $concatArrays: [ "$$value", { $map: { input: "$$this.amount", as: "item", in: { $toInt: { $last: "$$item" } } } } ] } } } } } } ])
正确输出结果
[ { "_id": ObjectId("5a934e000102030405000000"), "amount_sum": 100000000, "result": { "events": [ { "amount": [ [ 1623224700000, "33333333" ], [ 1623224760000, "33333333" ], [ 1623224820000, "33333334" ] ] } ] } } ]
内容的提问来源于stack exchange,提问作者Sander de Ruiter
相关产品推荐
相关产品推荐

