背景:
统计参加活动的用户总分排名信息
条件:
1、限制前一千名;
2、用户的战绩总分必须达到一千分;
3、时间不能超过XXXX,超过此时间获得的得分不计入排名计算中;
4、不允许并列一千,如分数相同,取先达到一千分的用户;
5、需要返回用户在没有超过指定时间之前一共玩了多少次游戏;
6、用户的战绩数据存储在mongoDB。
战绩信息存储结构:
{
"_id" : NumberLong(2111050000447937),
"activityId" : NumberLong(5),
"userId" : NumberLong(2111030000471143),
"score" : 36,
"isDeleted" : 0,
"createUserId" : NumberLong(0),
"createTime" : NumberLong(1636079718181),
"updateTime" : NumberLong(1636079738181),
"updateUserId" : NumberLong(0)
}
实现:
limit:限制前多少名,此场景中为1000;
endTime:进入总分计算的战绩数据创建的最大时间;
minScore:至少需要多少分,此场景中为1000。
public List<UserRankScoreModel> queryUserPeriodRankAndSumScoreByEndTime(Integer limit, Date endTime, Integer minScore) {
Aggregation aggregation = Aggregation.newAggregation(
// 条件一:必须要转类型,否则会查不到; lte:小于等于
Aggregation.match(Criteria.where("createTime").lte(endTime.getTime())),
// 分组
// first:返回字段; as:给返回的数据起别名;
Aggregation.group("userId").first("userId").as("userId").count().as("gameNum")
.sum("score").as("sumScore").max("createTime").as("maxTime"),
// 条件二:gte:大于等于
Aggregation.match(Criteria.where("sumScore").gte(Long.valueOf(minScore))),
// 排序
Aggregation.sort(Sort.Direction.DESC, "sumScore").and(Sort.Direction.ASC, "maxTime"),
// 分页 skip:从哪里开始(不包括起点),limit:显示多少条数据
Aggregation.skip(0L),
Aggregation.limit(limit));
// user_activity_score:collection; UserRankScoreModel:接收返回数据的model
AggregationResults<UserRankScoreModel> userRankScoreModels
= mongoTemplate.aggregate(aggregation, "user_activity_score", UserRankScoreModel.class);
return userRankScoreModels.getMappedResults();
}
- UserRankScoreModel.java:
public class UserRankScoreModel {
/**
* 用户id
*/
private Long userId;
/**
* 游戏次数
*/
private Integer gameNum;
/**
* 游戏总分
*/
private Integer sumScore;
public Long getUserId() {
return userId;
}
public void setUserId(Long userId) {
this.userId = userId;
}
public Integer getGameNum() {
return gameNum;
}
public void setGameNum(Integer gameNum) {
this.gameNum = gameNum;
}
public Integer getSumScore() {
return sumScore;
}
public void setSumScore(Integer sumScore) {
this.sumScore = sumScore;
}
}