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

如何使用MongoDB对集合分组并求和对象属性生成计算字段

MongoDB按duelId分组并统计选手总得分的实现方案

该需求可通过MongoDB聚合管道完全实现,具体方案如下:

需求说明

按duelId字段对比赛记录分组,保留分组内所有原始比赛记录,同时统计分组内每个选手的battlesWon总和作为新增得分字段。

现有数据结构

{
  "matches": [
    {
      "secondParticipant": {"name": "Maria","battlesWon": 2},
      "firstParticipant": {"name": "Fabio","battlesWon": 1},
      "duelId": "6c3e532d-3c0e-4438-8289-c86a4a51a102"
    },
    {
      "secondParticipant": {"name": "Fabio","battlesWon": 1},
      "firstParticipant": {"name": "Maria","battlesWon": 1},
      "duelId": "6c3e532d-3c0e-4438-8289-c86a4a51a102"
    },
    {
      "secondParticipant": {"name": "Luiz","battlesWon": 1},
      "firstParticipant": {"name": "Jose","battlesWon": 1},
      "duelId": "6c3e532d-3c0e-4438-8289-c86a4a51a666"
    }
  ]
}

实现思路

  1. 若原始文档外层嵌套matches数组,先用$unwind将数组拆分为独立的单条比赛文档
  2. $group阶段按duelId分组,用$push保留同组所有原始比赛记录,同时收集所有参赛选手的姓名和得分
  3. 展平收集到的选手数据,按选手姓名分组求和生成总得分对象
  4. 按需调整输出结构匹配预期格式

完整聚合查询代码

假设集合名为duels,聚合语句如下:

db.duels.aggregate([
  // 展开外层matches数组,若集合直接存储单条比赛记录可删除该阶段
  { $unwind: "$matches" },
  // 按duelId分组
  {
    $group: {
      _id: "$matches.duelId",
      matchList: { $push: "$matches" },
      allPlayers: {
        $push: {
          $concatArrays: [
            [ { name: "$matches.firstParticipant.name", score: "$matches.firstParticipant.battlesWon" } ],
            [ { name: "$matches.secondParticipant.name", score: "$matches.secondParticipant.battlesWon" } ]
          ]
        }
      }
    }
  },
  // 展平所有选手数组
  {
    $addFields: {
      allPlayers: {
        $reduce: {
          input: "$allPlayers",
          initialValue: [],
          in: { $concatArrays: ["$$value", "$$this"] }
        }
      }
    }
  },
  // 计算选手总得分
  {
    $addFields: {
      score: {
        $arrayToObject: {
          $map: {
            input: { $setUnion: "$allPlayers.name" },
            as: "playerName",
            in: {
              k: "$$playerName",
              v: {
                $sum: {
                  $map: {
                    input: {
                      $filter: {
                        input: "$allPlayers",
                        cond: { $eq: ["$$this.name", "$$playerName"] }
                      }
                    },
                    in: "$$this.score"
                  }
                }
              }
            }
          }
        }
      }
    }
  },
  // 默认输出结构化结果,如需匹配示例数组格式可替换为下方注释的阶段
  {
    $project: {
      _id: 0,
      duelId: "$_id",
      matchList: 1,
      score: 1
    }
  }
  /* 如需输出示例中的数组结构,替换上面的$project阶段为以下代码:
  {
    $project: {
      _id: 0,
      result: { $concatArrays: ["$matchList", [ { score: "$score" } ]] }
    }
  }
  */
])

输出结果说明

默认输出的结构化结果示例:

{
  "duelId": "6c3e532d-3c0e-4438-8289-c86a4a51a102",
  "matchList": [
    {
      "secondParticipant": {"name": "Maria","battlesWon": 2},
      "firstParticipant": {"name": "Fabio","battlesWon": 1},
      "duelId": "6c3e532d-3c0e-4438-8289-c86a4a51a102"
    },
    {
      "secondParticipant": {"name": "Fabio","battlesWon": 1},
      "firstParticipant": {"name": "Maria","battlesWon": 1},
      "duelId": "6c3e532d-3c0e-4438-8289-c86a4a51a102"
    }
  ],
  "score": {"Fabio": 2, "Maria": 3}
}

若使用替换后的数组结构输出,完全匹配你给出的预期格式。

内容的提问来源于stack exchange,提问作者Daywison Ferreira Leal

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 21:15:04