前言:今天在做项目的时候发现了一个Bug,记录下来
本来是要实现Top5,根据时间显示点赞的用户信息
(谁越早点赞,谁的显示就考前排)
我在redis里面是用sortedSet记录
key: 博客id
value:用户id
并且value对应的score是 时间戳
这样就可以实现根据谁越早点赞进行顺序排序
本以为这样就可以了…🤔🤔🤔
String key=RedisConstants.BLOG_LIKED_KEY+id;
Set<String> top5 = redisTemplate.opsForZSet().range(key, 0L, 4L);
//避免空指针
if(top5==null || top5.isEmpty()){
return Result.ok(Collections.emptyList());
}
List<Long> userIds = top5.stream().map(Long::valueOf).collect(Collectors.toList());
List<UserDTO> userDTOS = userService.listByIds(userIds)
.stream()
.map(user -> BeanUtil.copyProperties(user, UserDTO.class))
.collect(Collectors.toList());
return Result.ok(userDTOS);
//简单看一下,这个是业务代码
看似没有问题,但问题出现在了 sql 语句上
这个业务代码对应的sql语句
-- 假设用户id为5的点赞时间在用户id为1的点赞时间的前面
select
xxx
from tb_user
where id in(5,1)
问题就出在了 in(…)
在in里面查询的顺序可不是按照谁写在前谁写在后就先查顺
in里面根据id查询是乱序查询的
所以这就导致了返回结果的乱序现象
-- 假设用户id为5的点赞时间在用户id为1的点赞时间的前面
select
xxx
from tb_user
where id in(5,1)
order by Field(id,5,1)
//对应的业务代码如下
String key=RedisConstants.BLOG_LIKED_KEY+id;
Set<String> top5 = redisTemplate.opsForZSet().range(key, 0L, 4L);
//避免空指针
if(top5==null || top5.isEmpty()){
return Result.ok(Collections.emptyList());
}
List<Long> userIds = top5.stream().map(Long::valueOf).collect(Collectors.toList());
String ids = StrUtil.join(",", userIds);
List<UserDTO> userDTOS = userService.query()
.in("id",userIds)
.last("ORDER BY FIELD(id,"+ids+")") //自定义SQL语句
.list()
.stream()
.map(user -> BeanUtil.copyProperties(user, UserDTO.class))
.collect(Collectors.toList());
return Result.ok(userDTOS);