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的排名是集合

發佈了22 篇原創文章 · 獲贊 25 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章