MongoDB如何unwind对象内数组并合并两组玩家数组适配Mongo Charts展示
实现方案
核心思路
直接使用MongoDB原生聚合管道完成数据转换,全程无需额外脚本处理,处理后的数据可直接接入Mongo Charts使用,分四个核心阶段执行:
- 第一阶段提取两个队伍的players数组,剔除不需要的id字段,保留username、score、rank、prize字段
- 第二阶段合并两个队伍的players数组得到初始的all_winners列表,同时将字符串类型的score转为数值类型用于后续排序
- 第三阶段对all_winners按score数值降序排序
- 第四阶段为排序后的all_winners重新生成全局排名
完整聚合代码
db.collection.aggregate([ // 1. 提取两队players数组,剔除多余字段 { $project: { team_a: { $map: { input: "$team_a.players", as: "p", in: { username: "$$p.username", score: "$$p.score", rank: "$$p.rank", prize: "$$p.prize" } } }, team_b: { $map: { input: "$team_b.players", as: "p", in: { username: "$$p.username", score: "$$p.score", rank: "$$p.rank", prize: "$$p.prize" } } } } }, // 2. 合并数组并转score为数值类型 { $set: { all_winners: { $map: { input: { $concatArrays: ["$team_a", "$team_b"] }, as: "p", in: { $mergeObjects: [ "$$p", { score_num: { $toInt: "$$p.score" } } ] } } } } }, // 3. 按得分降序排序 { $set: { all_winners: { $sortArray: { input: "$all_winners", sortBy: { score_num: -1 } } } } }, // 4. 重新生成全局排名 { $set: { all_winners: { $map: { input: { $range: [0, { $size: "$all_winners" }] }, as: "idx", in: { $mergeObjects: [ { $arrayElemAt: ["$all_winners", "$$idx"] }, { rank: { $toString: { $add: ["$$idx", 1] } } } ] } } } } }, // 可选:移除临时字段score_num { $set: { all_winners: { $map: { input: "$all_winners", as: "p", in: { username: "$$p.username", score: "$$p.score", rank: "$$p.rank", prize: "$$p.prize" } } } } } ])
注意事项
- 如果你的MongoDB版本低于5.2,不支持
$sortArray运算符,可以将排序步骤替换为$unwind+$sort+$group的组合实现 - 若存在得分相同需要并列排名的需求,可以调整排名计算逻辑,加入得分对比的判断即可
内容的提问来源于stack exchange,提问作者Suneel K Khatri
相关产品推荐
相关产品推荐

