点赞需要注意:
主要思路:
Redis的Set集合(无序,元素不可重复)来解决:
1.推文的id拼接作为key,把当前用户的userid作为value。
2.如果Set存在value,说明点过赞了,update-1,然后remove移除Set集合。否则没点过赞,update-1,add添加userid到Ser集合中去。
/**
* 点赞
* @param id
* @return
*/
@Override
public Result likeBlog(Long id) {
Long userId = UserHolder.getUser().getId();
Boolean flag = stringRedisTemplate.opsForSet().isMember(RedisConstants.BLOG_LIKED_KEY+id, userId.toString());
//没点过赞
if(BooleanUtil.isFalse(flag)) {
boolean success = update().setSql("liked = liked + 1").eq("id", id).update();
if(success) {
stringRedisTemplate.opsForSet().add(RedisConstants.BLOG_LIKED_KEY+id, userId.toString());
}
} else {
//点过赞了
boolean success = update().setSql("liked = liked - 1").eq("id", id).update();
stringRedisTemplate.opsForSet().remove(RedisConstants.BLOG_LIKED_KEY+id,userId.toString());
}
return Result.ok();
}
/**
*我们每次查看博客推文的时候都要执行一下该方法
* 判断是否点过赞
* IsLike是让前端知道图标是否高亮显示
* @param blog
*/
private void isBlogLiked(Blog blog) {
Boolean member = stringRedisTemplate.opsForSet().isMember(RedisConstants.BLOG_LIKED_KEY + blog.getId(), UserHolder.getUser().getId().toString());
blog.setIsLike(BooleanUtil.isTrue(member));
}
点赞排行榜:
如同我们发朋友圈,别人可以来点赞,显示一些人,但是更多的点赞被折叠起来了。这个排行榜我们按照点赞时间顺序,来展示TOP5位。这时候Set集合因为是无序的就不太行了。我们可以使用Redis的ZSet
1.有序集合 Zset 中的 元素排序 , 是 根据 评分 进行排序 , 每个成员 都关联了一个 评分 , 在该 有序集合 中 , 根据 评分 由低到高 进行排序 ;
2.Zset 中的元素 是 不可重复的 , 但是 元素 关联 的 评分 是可以重复的 , 也就是说 存在 两个不同的元素 关联着 相同的 评分 ;
3.Zset 中的元素 是 有序 的 , 根据 排序的索引 或者 元素的评分 可以获取 指定范围 的 成员 ;我们的使用:
score评分我们添加的时间戳,先点赞的小,后面的逐渐增大
private void isBlogLiked(Blog blog) {
UserDTO user = UserHolder.getUser();
if(user == null) {
//用户为登录,无需查询点赞
return;
}
Double score = stringRedisTemplate.opsForZSet().score(RedisConstants.BLOG_LIKED_KEY + blog.getId(), UserHolder.getUser().getId().toString());
blog.setIsLike(score != null);
}
/**
* 点赞
* @param id
* @return
*/
@Override
public Result likeBlog(Long id) {
Long userId = UserHolder.getUser().getId();
Double score = stringRedisTemplate.opsForZSet().score(RedisConstants.BLOG_LIKED_KEY + id, userId.toString());
//没点过赞
if(score == null) {
update().setSql("liked = liked + 1").eq("id", id).update();
stringRedisTemplate.opsForZSet().add(RedisConstants.BLOG_LIKED_KEY+id, userId.toString(),System.currentTimeMillis());
} else {
//点过赞了
update().setSql("liked = liked - 1").eq("id", id).update();
stringRedisTemplate.opsForZSet().remove(RedisConstants.BLOG_LIKED_KEY+id,userId.toString());
}
return Result.ok();
}
/**
* 点赞排行榜
* @param id
* @return
*/
@Override
public Result queryBlogLikes(Long id) {
//查询TOP5个点赞的用户
Set<String> range = stringRedisTemplate.opsForZSet().range(RedisConstants.BLOG_LIKED_KEY + id, 0, 4);
if(range == null || range.isEmpty()) {
return Result.ok(Collections.emptyList());
}
//解析出id
List<Long> ids = range.stream().map(Long::valueOf).collect(Collectors.toList());
List<User> users = blogMapper.queryTOP5(ids);
//根据id查询用户
List<UserDTO> userDTOList = users.stream()
.map(user -> BeanUtil.copyProperties(user, UserDTO.class))
.collect(Collectors.toList());
return Result.ok(userDTOList);
}
<!--按照ids中的id顺序排序,我们引入了order by FIELD,不然查到的List<User>排序按照id大小-->
<select id="queryTOP5" resultType="com.hmdp.entity.User">
select * from tb_user where id in
<foreach collection="ids" item="id" open="(" close=")" separator=",">
#{id}
</foreach>
order by FIELD(id,
<foreach collection="ids" item="id" separator=",">
#{id}
</foreach>
)
</select>