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

MongoDB如何对文档数组按id分组聚合计算score平均值并更新state字段

MongoDB 文档处理:数组分组求平均 + 根字段修改

要实现你需要的文档转换,用MongoDB的聚合框架就能搞定,下面是完整的实现代码和分步解释:

完整聚合查询

db.collection.aggregate([
  // 更新根文档_id中的state字段
  {
    $addFields: {
      _id: {
        $mergeObjects: ["$_id", { state: "New York" }]
      }
    }
  },
  // 展开List数组,便于逐个处理元素
  { $unwind: "$List" },
  // 分组计算每个id对应的score平均值
  {
    $group: {
      _id: {
        rootId: "$_id",
        itemId: "$List.id",
        itemName: "$List.name"
      },
      avgScore: { $avg: "$List.score" }
    }
  },
  // 重新组装成目标文档结构
  {
    $group: {
      _id: "$_id.rootId",
      List: {
        $push: {
          id: "$_id.itemId",
          score: "$avgScore",
          name: "$_id.itemName"
        }
      }
    }
  }
])

分步解释每个阶段

  • $addFields 阶段:用$mergeObjects把原_id对象和新的state值合并,既替换了state为"New York",又保留了原有的st字段,不用手动重新写整个_id结构。
  • $unwind 阶段:把List数组拆成单个文档,这样每个数组元素都能独立参与后续的分组计算——毕竟MongoDB的分组操作是针对文档级别的,不展开的话没法直接对数组内元素分组。
  • 第一个$group 阶段:我们需要同时按「根文档的_id」「数组元素的id」「数组元素的name」来分组(确保同一个id对应的name不会出错),然后用$avg计算该组的score平均值。
  • 第二个$group 阶段:重新以根文档的_id为分组依据,用$push把每个分组的结果重新组装成List数组,还原成你需要的最终文档结构。

可选优化(如果name和id一一对应)

如果能确定同一个id对应的name完全一致(比如你的业务逻辑保证这点),可以简化第一个$group的分组键,用$first来获取name,减少分组维度:

// 替换第一个$group阶段
{
  $group: {
    _id: {
      rootId: "$_id",
      itemId: "$List.id"
    },
    avgScore: { $avg: "$List.score" },
    itemName: { $first: "$List.name" }
  }
}

然后第二个$group里的name就用$itemName即可,这样效率会稍高一些。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 13:33:14