Mongo实现实时获取用户排名查询

本文是Mongo语法实现的实时用户排名,支持Mongo3.4、4.2版本

 

数据样例

db.grade.insert({'name':'张三', 'grade':100});
db.grade.insert({'name':'李四', 'grade':95});
db.grade.insert({'name':'王五', 'grade':95});
db.grade.insert({'name':'赵六', 'grade':70});
db.grade.insert({'name':'李', 'grade':0});
db.grade.insert({'name':'钱', 'grade':0});

一、方案1:同分不同排名

如:李四、王五 分数一样,排名 可能是李四-2(王五-3),也可能王五-2

实现方案

按成绩降序排列,然后合并成数组(数组有下标,可以当排名用),再将数组拆分成多条记录,拆分时带上数组所在下标位置

Mongo语句

db.grade.aggregate([
{
    $sort:{
        'grade':-1
    }
},
// 将行转化为集合存储
{
    "$group": {
        "_id": null,
        "tableA": {
                "$push": "$$ROOT"
        }
    }
},
// 拆分集合为行,同时带上数组下标
{
    $unwind:{
        path:'$tableA',
        includeArrayIndex:'arrayIndex'
    }
},{
    $project:{
        '_id':0,
        'creatorName':'$tableA.name',
        'creatorId':'$tableA.grade',
        'arrayIndex':{
            $add:['$arrayIndex',1]
        }
    }
}
])

 

 

 

二、方案2: 同分同排名,排名连续

如:李四、王五 分数一样,排名: 张三-1,李四-2,王五-2,赵六-3
注:赵六是第三名而不是第四名

实现原理

首先 获取 分数所在的排名,然后关联用户分数表,将用户的分数与排名关联上,获取的就是该用户的排名

Mongo语句

db.grade.aggregate([
{
// 获取分数所在排名
    $group:{
        '_id':'$grade',
        'grade':{
            $first:'$grade'
        }
    }
},{
    $sort:{'grade':-1}
},{
    $group:{
        "_id": null,
        "tableA": {
                "$push": "$$ROOT"
        }
    }
},{
    $unwind:{
        path:'$tableA',
        includeArrayIndex:'arrayIndex'
    }
},{
    $project:{
        '_id':0,
        'grade':'$tableA.grade',
        'arrayIndex':{
            $add:['$arrayIndex',1]
        }
    }
},
// 关联用户成绩表
{
    $lookup:{
         "from": "grade",
            "localField": "grade",
            "foreignField": "grade",
            "as": "userGrade"
    }
},{
    $unwind:'$userGrade'
},{
    $project:{
        'creatorName':'$userGrade.name',
        'creatorId':'$userGrade.grade',
        'arrayIndex':1
    }
}
])

 

 

 

三、 扩展-同分不同排名-获取当前用户排名和前n的排名

Mongo语句

db.grade.aggregate([
{
    $sort:{
        'grade':-1
    }
},
// 将行转化为集合存储
{
    "$group": {
        "_id": null,
        "tableA": {
                "$push": "$$ROOT"
        }
    }
},
// 拆分集合为行,同时带上数组下标
{
    $unwind:{
        path:'$tableA',
        includeArrayIndex:'arrayIndex'
    }
},{
    $project:{
        '_id':0,
        'name':'$tableA.name',
        'creatorId':'$tableA.grade',
        'arrayIndex':{
            $add:['$arrayIndex',1]
        }
    }
},
// 对同一数据进行两次不同操作
{
    $facet:{
        'my':[
            {
                $match:{
                    'name':'李四'
                }
            }
        ],
// 测试获取前五的排名
        'top':[{
                $limit:5
            },{
                $skip:0
            }
        ]
    }
}
])

仅返回一行记录
字段:my 存储我的排名是集合
字段:top 存储前n的排名是集合

 

转载至:https://blog.csdn.net/u013494765/article/details/103620445

posted @ 2022-08-05 14:37  浅笑19  阅读(487)  评论(0编辑  收藏  举报