Mongoose中按totalCoins、level排序查询指定玩家排名的方法
Mongoose实现多规则玩家排名查询
排序规则说明
排名优先级从高到低:
- 按
totalCoins字段降序(金币越高排名越靠前) - 金币相同的情况下,按
level字段降序(等级越高排名越靠前)
如果需要同分不并列,可以在最后补充次级排序规则,比如按_id升序/注册时间升序即可
前置性能优化(10w+数据必做)
提前创建匹配排序规则的复合索引,避免全表扫描和内存排序,查询耗时可以降到毫秒级:
// 在Player Schema上创建复合索引 const playerSchema = new mongoose.Schema({ // 原有字段定义... }) // 索引字段排序方向和查询排序方向保持一致 playerSchema.index({ totalCoins: -1, level: -1, _id: 1 }) const Player = mongoose.model('Player', playerSchema)
方案1:计数法(性能最优,推荐单玩家排名查询场景)
核心逻辑:先拿到目标玩家的金币、等级数值,统计所有排名比他高的玩家总数,最终排名 = 高排名玩家数 + 1。
async function getPlayerRank(playerId) { // 1. 查询目标玩家的排序字段值 const target = await Player.findById(playerId, 'totalCoins level _id') if (!target) throw new Error('玩家不存在') // 2. 统计所有排名高于目标玩家的数量 const higherCount = await Player.countDocuments({ $or: [ // 金币比目标高的,排名一定靠前 { totalCoins: { $gt: target.totalCoins } }, // 金币相同、等级比目标高的,排名靠前 { totalCoins: target.totalCoins, level: { $gt: target.level } }, // (可选)金币等级都相同,按_id升序排的话,_id更小的排名靠前,不需要并列排名就加这一条 { totalCoins: target.totalCoins, level: target.level, _id: { $lt: target._id } } ] }) // 3. 返回最终排名 return higherCount + 1 } // 调用示例:查询_id=4的玩家排名 const rank = await getPlayerRank(4)
这个方案不需要拉取全表数据排序,走索引的count操作资源消耗极低,10w-百万级数据量都适用。
按照给出的示例数据计算,_id=4的玩家用这个方案查询返回的排名是3,符合预期。
方案2:窗口函数聚合(适合连带返回排名列表场景)
如果使用MongoDB 5.0及以上版本,需要同时返回玩家信息+排名、或者需要查询某玩家前后的排名列表,可以用$setWindowFields窗口函数直接生成排名:
async function getPlayerRankWithInfo(playerId) { const result = await Player.aggregate([ // 按规则排序,走提前创建的复合索引 { $sort: { totalCoins: -1, level: -1, _id: 1 } }, // 生成排名字段 { $setWindowFields: { sortBy: { totalCoins: -1, level: -1, _id: 1 }, output: { rank: { // $denseRank: 同分同名次,比如两个第3名,下一名是第4 // $rank: 同分跳号,比如两个第3名,下一名是第5 $denseRank: {} } } } }, // 匹配目标玩家 { $match: { _id: playerId } }, // 自定义返回字段 { $project: { name: 1, totalCoins: 1, level: 1, rank: 1 } } ]) return result[0] } // 调用示例 const playerInfo = await getPlayerRankWithInfo(4) // 返回结构:{ _id:4, name:'def', totalCoins:100, level:4, rank:3 }
注意:MongoDB版本低于5.0不支持窗口函数,直接用方案1即可。
内容的提问来源于stack exchange,提问作者Jaspreet Singh
相关产品推荐
相关产品推荐

