You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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
  }
]

问题原因及解决方案

错误原因

  1. 变量引用错误:内层$map使用$events引用外层变量,正确的引用方式应为$$events(MongoDB聚合中,$引用字段路径,$$引用自定义变量)。
  2. 遍历对象而非数组:内层$map的input设为$$events(即单个event对象),但实际需要遍历的是$$events.amount数组。
  3. 二维数组无法直接求和:即使修正前两点,嵌套$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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 12:01:07