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

MongoDB聚合管道:将前阶段数组结果转换为对象

将MongoDB聚合结果数组转为单个对象(使用$project + $reduce)

首先咱们得理清逻辑:你的$match阶段返回的是多个独立文档,要把它们转成单个对象,第一步得先把这些文档收集到一个数组里(不然$reduce没东西可遍历),接着再用$reduce来处理这个数组。

这里给你完整的管道实现,在$match之后的后续阶段如下:

const pipeline = [
  { $match: query }, // 你的第一个管道阶段
  // 阶段2:把所有匹配的文档收集到一个数组中
  {
    $group: {
      _id: null, // 不按任何字段分组,将所有结果聚合成一组
      documents: { $push: "$$ROOT" } // 把每个完整文档推到documents数组里
    }
  },
  // 阶段3:用$project结合$reduce将数组转为单个对象
  {
    $project: {
      _id: 0, // 移除自动生成的_id字段
      result: {
        $reduce: {
          input: "$documents", // 指定要遍历的目标数组
          initialValue: {}, // 累加器的初始状态设为空对象
          in: {
            // 将当前遍历到的文档合并到累加器对象中
            $mergeObjects: ["$$value", "$$this"]
          }
        }
      }
    }
  }
];

关键部分解释:

  • $group阶段:因为$match返回的是分散的文档,必须先把它们打包成数组才能用$reduce处理。_id: null表示不按任何字段分组,把所有结果归为一组;$push: "$$ROOT"会把每个完整的文档添加到documents数组里。
  • $project中的$reduce:
    • input指定要遍历的数组就是我们刚收集的documents
    • initialValue是累加器的初始状态,这里设为空对象
    • in是每次遍历执行的逻辑,用$mergeObjects把当前文档($$this)和累加器里的对象($$value)合并。如果有重复字段,后面的文档会覆盖前面的(比如你的示例里,第二个文档的score和views会替换第一个的)。

如果需要聚合数值(比如求和score和views):

要是你不是单纯合并对象,而是想对相同author的数值做聚合(比如求和),可以修改$reduce的in逻辑:

{
  $project: {
    _id: 0,
    result: {
      $reduce: {
        input: "$documents",
        initialValue: { author: "", score: 0, views: 0 },
        in: {
          author: "$$this.author", // 示例中author都是dave,直接取当前值即可
          score: { $add: ["$$value.score", "$$this.score"] },
          views: { $add: ["$$value.views", "$$this.views"] }
        }
      }
    }
  }
}

这样得到的结果会是:{ result: { author: "dave", score: 165, views: 621 } }

注意事项:

  • 如果文档里有重复字段且不想被覆盖,得提前规划好合并逻辑(比如把重复字段转成数组)
  • $mergeObjects只会合并顶层字段,如果有嵌套对象,需要额外处理

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 09:02:49