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

文章目录

    • 数据样例
    • 一、方案1:同分不同排名
      • 实现方案
      • Mongo语句
    • 二、方案2: 同分同排名,排名连续
      • 实现原理
      • Mongo语句
    • 三、 扩展-同分不同排名-获取当前用户排名和前n的排名
      • 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]
		}
	}
}
])

Mongo实现实时获取用户排名查询_第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
	}
}
])

Mongo实现实时获取用户排名查询_第2张图片

三、 扩展-同分不同排名-获取当前用户排名和前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的排名是集合

你可能感兴趣的:(Mongo)