1、redis有序集合
sorted set 是在 Sets 的基础上增加了分数设置作为排序依据,所以除了具备 Sets 的特性外,还可以进行排序。它提供了一个 score 属性,正好可以用来做排序依据。
2、单字段排序
用户类
@Data
@NoArgsConstructor
@AllArgsConstructor
public class UserDTO {
private Long id;
private String name;
/**
* 创建时间
*
* @author: ybw
* @date: 2023/3/24
**/
private LocalDateTime createDateTime;
/**
* 积分
*
* @author: ybw
* @date: 2023/3/24
**/
private Long point;
}
初始化数据,根据createDateTime排序
public void init() {
for (long i = 0L; i < 1000L; i++) {
UserDTO userDTO = new UserDTO(i, "zhangsan" + i, LocalDateTime.now().plusDays(i%500),i);
// 按时间排序
redisTemplate.opsForZSet().add(key, userDTO, userDTO.getCreateDateTime().toInstant(ZoneOffset.of("+8")).toEpochMilli());
}
}
分页查询
public void page() {
//页码
int pageNum = 1;
//一页条数
int pageSize = 20;
int start = (pageNum - 1) * pageSize;
int end = start + pageSize - 1;
// 时间从小到大排序
Set<UserDTO> set = redisTemplate.opsForZSet().range(key, start, end);
log.info("set:{}", JSON.toJSONString(set));
}
打印日志如下,可以看到createDateTime升序返回的:
[{
"createDateTime": "2023-03-24T11:01:33.470",
"id": 0,
"name": "zhangsan0",
"point": 0
}, {
"createDateTime": "2023-03-24T11:01:36.343",
"id": 500,
"name": "zhangsan500",
"point": 500
}, {
"createDateTime": "2023-03-25T11:01:36.143",
"id": 1,
"name": "zhangsan1",
"point": 1
}, {
"createDateTime": "2023-03-25T11:01:36.343",
"id": 501,
"name": "zhangsan501",
"point": 501
}, {
"createDateTime": "2023-03-26T11:01:36.144",
"id": 2,
"name": "zhangsan2",
"point": 2
}, {
"createDateTime": "2023-03-26T11:01:36.343",
"id": 502,
"name": "zhangsan502",
"point": 502
}, {
"createDateTime": "2023-03-27T11:01:36.146",
"id": 3,
"name": "zhangsan3",
"point": 3
}, {
"createDateTime": "2023-03-27T11:01:36.344",
"id": 503,
"name": "zhangsan503",
"point": 503
}, {
"createDateTime": "2023-03-28T11:01:36.146",
"id": 4,
"name": "zhangsan4",
"point": 4
}, {
"createDateTime": "2023-03-28T11:01:36.344",
"id": 504,
"name": "zhangsan504",
"point": 504
}, {
"createDateTime": "2023-03-29T11:01:36.147",
"id": 5,
"name": "zhangsan5",
"point": 5
}, {
"createDateTime": "2023-03-29T11:01:36.344",
"id": 505,
"name": "zhangsan505",
"point": 505
}, {
"createDateTime": "2023-03-30T11:01:36.148",
"id": 6,
"name": "zhangsan6",
"point": 6
}, {
"createDateTime": "2023-03-30T11:01:36.344",
"id": 506,
"name": "zhangsan506",
"point": 506
}, {
"createDateTime": "2023-03-31T11:01:36.148",
"id": 7,
"name": "zhangsan7",
"point": 7
}, {
"createDateTime": "2023-03-31T11:01:36.344",
"id": 507,
"name": "zhangsan507",
"point": 507
}, {
"createDateTime": "2023-04-01T11:01:36.150",
"id": 8,
"name": "zhangsan8",
"point": 8
}, {
"createDateTime": "2023-04-01T11:01:36.345",
"id": 508,
"name": "zhangsan508",
"point": 508
}, {
"createDateTime": "2023-04-02T11:01:36.152",
"id": 9,
"name": "zhangsan9",
"point": 9
}, {
"createDateTime": "2023-04-02T11:01:36.345",
"id": 509,
"name": "zhangsan509",
"point": 509
}]
3、多字段排序
sorted set可以通过score进行单字段排序,如果是多字段排序,如下面的sql,如何实现呢?
select * from user order by score desc,name desc;
3.1 按创建时间升序、积分降序
UserDTO不变、page(分页查询)不变,修改初始化代码。
限制条件:用户积分不能超过1000。代码实现
public void init() {
for (long i = 0L; i < 1000L; i++) {
UserDTO userDTO = new UserDTO(i, "zhangsan" + i, LocalDateTime.now().plusDays(i % 500).with(LocalTime.MIN), i);
//积分不超过1000
Long pointLimit=1000L;
// 按时间升序、积分降序
double score = userDTO.getCreateDateTime().toInstant(ZoneOffset.of("+8")).toEpochMilli()*pointLimit + (pointLimit - userDTO.getPoint());
redisTemplate.opsForZSet().add(key, userDTO, score);
}
}
分页查询日志,在createDateTime相同的情况下,按point降序排列。
[{
"createDateTime": "2023-03-24T00:00:00",
"id": 500,
"name": "zhangsan500",
"point": 500
}, {
"createDateTime": "2023-03-24T00:00:00",
"id": 0,
"name": "zhangsan0",
"point": 0
}, {
"createDateTime": "2023-03-25T00:00:00",
"id": 501,
"name": "zhangsan501",
"point": 501
}, {
"createDateTime": "2023-03-25T00:00:00",
"id": 1,
"name": "zhangsan1",
"point": 1
}, {
"createDateTime": "2023-03-26T00:00:00",
"id": 502,
"name": "zhangsan502",
"point": 502
}, {
"createDateTime": "2023-03-26T00:00:00",
"id": 2,
"name": "zhangsan2",
"point": 2
}, {
"createDateTime": "2023-03-27T00:00:00",
"id": 503,
"name": "zhangsan503",
"point": 503
}, {
"createDateTime": "2023-03-27T00:00:00",
"id": 3,
"name": "zhangsan3",
"point": 3
}, {
"createDateTime": "2023-03-28T00:00:00",
"id": 504,
"name": "zhangsan504",
"point": 504
}, {
"createDateTime": "2023-03-28T00:00:00",
"id": 4,
"name": "zhangsan4",
"point": 4
}, {
"createDateTime": "2023-03-29T00:00:00",
"id": 505,
"name": "zhangsan505",
"point": 505
}, {
"createDateTime": "2023-03-29T00:00:00",
"id": 5,
"name": "zhangsan5",
"point": 5
}, {
"createDateTime": "2023-03-30T00:00:00",
"id": 506,
"name": "zhangsan506",
"point": 506
}, {
"createDateTime": "2023-03-30T00:00:00",
"id": 6,
"name": "zhangsan6",
"point": 6
}, {
"createDateTime": "2023-03-31T00:00:00",
"id": 507,
"name": "zhangsan507",
"point": 507
}, {
"createDateTime": "2023-03-31T00:00:00",
"id": 7,
"name": "zhangsan7",
"point": 7
}, {
"createDateTime": "2023-04-01T00:00:00",
"id": 508,
"name": "zhangsan508",
"point": 508
}, {
"createDateTime": "2023-04-01T00:00:00",
"id": 8,
"name": "zhangsan8",
"point": 8
}, {
"createDateTime": "2023-04-02T00:00:00",
"id": 509,
"name": "zhangsan509",
"point": 509
}, {
"createDateTime": "2023-04-02T00:00:00",
"id": 9,
"name": "zhangsan9",
"point": 9
}]
4、源代码
https://gitee.com/xixingzhe2/share/tree/master/redis/redis-page