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

如何在MongoDB中分组多轮高尔夫赛事数据生成排行榜?

解决多轮高尔夫比赛的排行榜统计问题

嘿,我来帮你搞定这个多轮成绩统计的需求!你之前用循环的思路方向是对的,但MongoDB本身提供的聚合框架,能更高效、简洁地实现分组累加需求,不用手动处理数组遍历和更新的繁琐逻辑。

核心思路

我们需要完成这几个关键步骤:

  • 先筛选出目标matchId对应的所有轮次ID(从rounds集合)
  • 基于这些轮次ID,从roundScores中获取所有相关的球员成绩
  • 按playerId分组,累加每个球员的toPar和points
  • 按toPar升序排序(高尔夫中toPar越低成绩越好),生成最终排行榜

正确的MongoDB聚合查询代码

直接用聚合管道就能一步到位,比你写的循环高效太多:

db.roundScores.aggregate([
  // 第一步:关联rounds集合,匹配对应matchId的轮次
  {
    $lookup: {
      from: "rounds",
      localField: "roundId",
      foreignField: "_id",
      as: "roundInfo"
    }
  },
  // 过滤出目标matchId的成绩记录
  {
    $match: {
      "roundInfo.matchId": matchId
    }
  },
  // 展开关联的轮次信息数组(lookup返回的是数组,需转为单条记录)
  { $unwind: "$roundInfo" },
  // 按playerId分组,累加toPar和points总和
  {
    $group: {
      _id: "$playerId",
      totalToPar: { $sum: "$toPar" },
      totalPoints: { $sum: "$points" }
    }
  },
  // 按总toPar升序排序(成绩越好越靠前)
  {
    $sort: { totalToPar: 1 }
  },
  // 可选:调整输出字段名,让结果更直观
  {
    $project: {
      playerId: "$_id",
      totalToPar: 1,
      totalPoints: 1,
      _id: 0
    }
  }
])

代码逐段解释

  1. $lookup:将roundScores和rounds集合通过roundId关联,拿到每个成绩对应的赛事matchId信息。
  2. $match:只保留目标赛事下的成绩记录,过滤掉无关数据。
  3. $unwind:把$lookup返回的数组型轮次信息展开为单条记录,方便后续分组操作。
  4. $group:核心步骤——按playerId分组,用$sum算子自动累加每个球员的toPar和points总和。
  5. $sort:按照累加后的totalToPar升序排序,符合高尔夫的排名规则(低于标准杆越多,排名越靠前)。
  6. $project:可选步骤,重命名字段(比如把默认的_id改成playerId),让输出结果更易读。

针对你之前循环代码的优化说明

你之前的循环思路需要手动遍历所有轮次和成绩,还要自己在数组中查找对应球员更新数据,不仅代码繁琐,而且数据量较大时效率会很低。用聚合框架的话,这些逻辑都由MongoDB引擎优化处理,代码更简洁,执行效率也更高。

示例数据验证

用你给出的示例数据测试,最终输出结果会是:

[
  { "playerId": "54354245566", "totalToPar": 1, "totalPoints": 54 },
  { "playerId": "12653426518", "totalToPar": 4, "totalPoints": 56 }
]

(注:你给出的期望结果中points数值看起来可能是笔误,按示例数据累加应为31+23=54和27+29=56)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 08:08:51