如何用MongoDB聚合统计彩票游戏中用户号码的匹配次数
彩票游戏用户号码与中奖号匹配统计的MongoDB实现方案
需求概述
我正在开发一款彩票游戏,核心需求如下:
- 用户提交由1-9组成的4位号码(示例:
1, 4, 5, 8) - 通过
Math.random()生成中奖的4位号码 - 需要统计每位用户号码与中奖号码的匹配次数,并区分出匹配0、1、2、3、4次的用户群体
现有两种思路分析
思路一:新增matchesMade字段
- 操作逻辑:每次生成新的中奖号码后,遍历所有用户文档,计算其号码与中奖号的匹配次数,更新文档中的
matchesMade字段 - 优势:后续统计时只需基于该字段做简单分组查询,效率较高
- 劣势:中奖号更新时需批量修改所有用户文档,用户量较大时性能开销显著
思路二:分5次查询不同匹配次数的用户
- 操作逻辑:针对匹配0到4次的每种情况,分别编写查询语句,每次查询对应匹配次数的用户
- 优势:无需修改现有文档结构,中奖号更新时无需额外预处理
- 劣势:需要执行5次独立查询,统计效率低,代码冗余度高
推荐:单次聚合查询完成全量统计
可以通过MongoDB的聚合管道,一次性完成所有匹配次数的统计,兼顾效率与代码简洁性。假设用户文档结构如下:
{ "userId": "user_001", "numbers": [1, 4, 5, 8] // 用户提交的4位号码存储为数组 }
以下是聚合查询示例(中奖号码以[2, 4, 7, 8]为例,实际使用时可替换为Math.random()生成的结果):
db.users.aggregate([ // 注入中奖号码并计算每个用户的匹配次数 { $addFields: { winningNumbers: [2, 4, 7, 8], matchCount: { $size: { $filter: { input: "$numbers", as: "num", cond: { $in: ["$$num", "$winningNumbers"] } } } } }}, // 按匹配次数分组,统计用户列表和数量 { $group: { _id: "$matchCount", userList: { $push: "$userId" }, totalUsers: { $sum: 1 } }}, // 补全0-4次匹配的分组(避免无用户时缺失类别) { $unionWith: { coll: { $documents: [ { _id: 0, userList: [], totalUsers: 0 }, { _id: 1, userList: [], totalUsers: 0 }, { _id: 2, userList: [], totalUsers: 0 }, { _id: 3, userList: [], totalUsers: 0 }, { _id: 4, userList: [], totalUsers: 0 } ] } }}, // 去重并保留真实统计数据 { $group: { _id: "$_id", userList: { $first: { $cond: [{ $ne: ["$userList", []] }, "$userList", "$$REMOVE"] } }, totalUsers: { $max: "$totalUsers" } }}, // 按匹配次数升序排序 { $sort: { _id: 1 } } ])
方案说明
- 计算匹配次数:通过
$filter筛选出用户号码中存在于中奖号的元素,再用$size获取匹配数量 - 分组统计:按匹配次数分组,收集对应用户ID并统计用户数
- 补全类别:用
$unionWith添加0-4次匹配的空分组,确保所有类别都能在结果中显示 - 去重整理:合并重复分组,移除无用户的空列表,保留真实统计值
- 排序输出:按匹配次数升序排列,结果更直观
内容的提问来源于stack exchange,提问作者user874737
相关产品推荐
相关产品推荐

