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

如何将MongoDB聚合管道中$group的最值结果合并回原始文档

MongoDB 按level分组计算最值并合并回原始文档

需求说明

按level字段分组,计算每组内x、y字段的最大值和最小值,将这些结果以动态命名的字段(如max_level_6_x)添加到对应level的每一条原始文档中,保留原始文档的所有字段供后续聚合阶段使用。

解决方案

方法一:使用$setWindowFields(MongoDB 5.0+ 推荐)

该方法无需分组后再关联,直接在原始文档上添加分组统计值,性能更优:

db.collection.aggregate([
  {
    $setWindowFields: {
      partitionBy: "$level",
      output: {
        stats: {
          $mergeObjects: {
            max_x: { $max: "$x" },
            min_x: { $min: "$x" },
            max_y: { $max: "$y" },
            min_y: { $min: "$y" }
          }
        }
      }
    }
  },
  {
    $set: {
      dynamicStats: {
        $arrayToObject: [
          [
            { k: { $concat: ["max_level_", "$level", "_x"] }, v: "$stats.max_x" },
            { k: { $concat: ["min_level_", "$level", "_x"] }, v: "$stats.min_x" },
            { k: { $concat: ["max_level_", "$level", "_y"] }, v: "$stats.max_y" },
            { k: { $concat: ["min_level_", "$level", "_y"] }, v: "$stats.min_y" }
          ]
        ]
      }
    }
  },
  {
    $replaceRoot: {
      newRoot: { $mergeObjects: ["$$ROOT", "$dynamicStats"] }
    }
  },
  {
    $unset: ["stats", "dynamicStats"]
  }
])

阶段解释:

  • $setWindowFields:按level分区,计算每个分区内x、y的最值并存入临时stats字段,保留所有原始文档。
  • $set:通过$concat生成目标字段名(如max_level_6_x),结合统计值构造dynamicStats对象。
  • $replaceRoot:将原始文档与dynamicStats合并,作为新的根文档。
  • $unset:移除临时字段,得到最终结构。

方法二:兼容旧版本(MongoDB 3.2+)

如果使用低于5.0的MongoDB版本,可通过$group+$unwind+$replaceRoot实现:

db.collection.aggregate([
  // 分组计算最值并保存原始文档列表
  {
    $group: {
      _id: "$level",
      max_x: { $max: "$x" },
      min_x: { $min: "$x" },
      max_y: { $max: "$y" },
      min_y: { $min: "$y" },
      docs: { $push: "$$ROOT" }
    }
  },
  // 展开原始文档列表
  { $unwind: "$docs" },
  // 合并原始文档与统计字段
  {
    $replaceRoot: {
      newRoot: {
        $mergeObjects: [
          "$docs",
          {
            $arrayToObject: [
              [
                { k: { $concat: ["max_level_", "$_id", "_x"] }, v: "$max_x" },
                { k: { $concat: ["min_level_", "$_id", "_x"] }, v: "$min_x" },
                { k: { $concat: ["max_level_", "$_id", "_y"] }, v: "$max_y" },
                { k: { $concat: ["min_level_", "$_id", "_y"] }, v: "$min_y" }
              ]
            ]
          }
        ]
      }
    }
  }
])

阶段解释:

  • $group:按level分组计算最值,同时用$push将该分组的所有原始文档存入docs数组。
  • $unwind:将docs数组展开,每条原始文档单独成为一个文档,携带分组的最值数据。
  • $replaceRoot:把原始文档与动态生成的统计字段合并,得到目标结构。

内容的提问来源于stack exchange,提问作者Shaun

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 04:15:39