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

MongoDB聚合查询扩展需求:新增获胜次数统计与带平局规则的积分计算字段

实现MongoDB聚合扩展:统计获胜次数与平局积分

完全可以基于你现有的文档结构实现这两个需求!下面我会给出完整的聚合查询代码,并拆解每一步的逻辑,帮你理解如何计算wins和平局规则下的points。

核心思路拆解

1. 统计wins(第1名次数)

这个逻辑比较直接:只需要统计每个玩家在所有对局中排名为1的次数,用$sum配合$cond条件判断即可实现。

2. 计算平局规则下的points

这部分相对复杂,需要先处理同一对局内的平局情况:

  • 先按对局分组,统计每个排名的玩家数量
  • 用等差数列求和逻辑计算平局时的平均得分(比如2人并列第1时,平分3+2的总分,得到2.5分)
  • 最后按玩家累加所有对局的得分

完整聚合查询代码

db.games.aggregate([
  // 1. 展开每局的玩家排名记录,方便后续逐条处理
  { $unwind: "$placements" },
  // 2. 按对局ID + 排名分组,统计该排名的玩家数量,同时保留玩家列表与单局统计数据
  {
    $group: {
      _id: { gameId: "$_id", rank: "$placements.rank" },
      players: { $push: "$placements.player" },
      rankCount: { $sum: 1 },
      playerStats: { $push: { plusMinus: "$placements.plusMinus", throws: "$placements.throws" } }
    }
  },
  // 3. 计算当前排名对应的平均得分(处理平局)
  {
    $set: {
      avgScore: {
        $divide: [
          { $subtract: [ { $subtract: [9, { $multiply: [2, "$_id.rank"] }] }, "$rankCount" ] },
          2
        ]
      }
    }
  },
  // 4. 展开玩家列表,关联每个玩家的单局得分与统计数据,标记是否获胜
  { $unwind: { path: "$players", includeArrayIndex: "statIndex" } },
  {
    $set: {
      currentPlusMinus: { $arrayElemAt: ["$playerStats.plusMinus", "$statIndex"] },
      currentThrows: { $arrayElemAt: ["$playerStats.throws", "$statIndex"] },
      isWin: { $eq: ["$_id.rank", 1] }
    }
  },
  // 5. 按玩家分组,累加所有数据
  {
    $group: {
      _id: "$players",
      wins: { $sum: { $cond: ["$isWin", 1, 0] } },
      points: { $sum: "$avgScore" },
      totalPlusMinus: { $sum: "$currentPlusMinus" },
      totalThrows: { $sum: "$currentThrows" }
    }
  },
  // 6. 格式化输出字段,匹配你想要的结构
  {
    $project: {
      _id: 0,
      player: "$_id",
      wins: 1,
      points: 1,
      "total+/-": "$totalPlusMinus",
      totalThrows: 1
    }
  },
  // 可选:按总积分降序排序
  { $sort: { points: -1 } }
])

代码逻辑解释

  • 步骤1:$unwind展开placements数组,把每局的多个玩家记录拆成单条文档,方便后续逐条处理。
  • 步骤2:按对局+排名分组,统计同一排名的玩家数量——这是计算平局平均分的核心依据,同时保留玩家的单局+/-和投掷次数用于后续累加。
  • 步骤3:用公式(9 - 2*rank - rankCount)/2计算平局平均得分,这个公式是根据你的积分规则推导的:
    • 第1名3分=4-1,第2名2分=4-2,第3名1分=4-3
    • 当有t个玩家并列第r名时,他们平分从r到r+t-1的名次分总和,用等差数列求和简化后得到该公式
  • 步骤4:再次展开玩家列表,关联每个玩家的单局统计数据,同时标记该局是否为获胜局(排名=1)。
  • 步骤5:按玩家最终分组,累加获胜次数、总积分、总+/-和总投掷次数。
  • 步骤6:调整输出字段名称,完全匹配你期望的结构。

示例输出

运行上述查询后,会得到符合你需求的结果:

[
  {
    "player": "Tormod",
    "wins": 2,
    "points": 7.5,
    "total+/-": 24,
    "totalThrows": 148
  },
  {
    "player": "Martin",
    "points": 7.5,
    "total+/-": 25,
    "totalThrows": 149,
    "wins": 2
  },
  {
    "player": "Andreas",
    "total+/-": 34,
    "points": 3,
    "wins": 0,
    "totalThrows": 158
  }
]

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 12:37:29