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
相关产品推荐
相关产品推荐

