【Redis】hmdp点赞、排行榜、分页功能的实现
创始人
2024-05-21 09:55:25

【Redis】hmdp点赞、排行榜、分页功能的实现

文章目录

  • 【Redis】hmdp点赞、排行榜、分页功能的实现
    • 1.点赞功能实现
      • 1.1 需求
      • 1.2 实现步骤
      • 1.3 思路分析
      • 1.4 代码实现
      • 1.5 逻辑解析
    • 2. 排行榜功能实现
      • 2.1 需求
      • 2.2 实现步骤
      • 2.3 思路分析
      • 2.4 代码实现
      • 2.5 逻辑解析
    • 3. 分页功能实现
      • 3.1 需求
      • 3.2 实现步骤
      • 3.3 代码实现
      • 3.4 逻辑解析

1.点赞功能实现


1.1 需求

需求:

  • 同一个用户只能点赞一次,再次点击则取消点赞
  • 如果当前用户已经点赞,则点赞按钮高亮显示(前端已实现,判断字段Blog类的isLike属性)

1.2 实现步骤

实现步骤:

  1. 给Blog类中添加一个isLike字段,标示是否被当前用户点赞
  2. 修改点赞功能,利用Redis的set集合判断是否点赞过,未点赞过则点赞数+1,已点赞过则点赞数-1
  3. 修改根据id查询Blog的业务,判断当前登录用户是否点赞过,赋值给isLike字段
  4. 修改分页查询Blog业务,判断当前登录用户是否点赞过,赋值给isLike字段

1.3 思路分析

在实现点赞功能前,我们还需要确定如何使用Redis来存储用户点赞记录?我们知道Redis存储的是键值对数据,那么我们可以先确定“键”的取值为:blog:liked:用户id ,“值”的取值为 用户id。确定好存储的数据之后,我们还需要考虑究竟是我们使用redis的哪种数据结构?因为点赞是有先后顺序的,所以我们采用 SortSet 结构,需求和实现步骤都明晰了后我们开始实现。

点击点赞按钮,发送请求:

image-20230131145255229


1.4 代码实现

代码如下:

@Override
public Result likeBlog(Long id) {//1.获取当前用户Long userId = UserHolder.getUser().getId();//2.判断当前用户是否已经点赞String key = "blog:liked:" + id;Double score = stringRedisTemplate.opsForZSet().score(key, userId.toString());if (score == null) {//3.如果未点赞,可以点赞//3.1数据库点赞+1boolean isSuccess = lambdaUpdate().setSql("liked=liked+1").eq(Blog::getId, id).update();//3.2.保存用户到redis的SortSet集合 ZADD KEY VALUE SCOREif (isSuccess) {stringRedisTemplate.opsForZSet().add(key, userId.toString(), System.currentTimeMillis());}} else {//4.如果已点赞,取消点赞//4.1.数据库点赞数-1boolean isSuccess = lambdaUpdate().setSql("liked=liked-1").eq(Blog::getId, id).update();if (isSuccess) {//4.2.把用户从Redis的set集合移除stringRedisTemplate.opsForZSet().remove(key, userId.toString());}}return Result.ok();
}

1.5 逻辑解析

代码逻辑:首先获得笔记id,拼接获得key值,再获得当前登录用户的id,根据用户id和key值查看redis中是否有数据,如果没有数据,说明未点赞,此时可以点赞,数据库对应字段+1,并且将用户id存入redis当中,score值存入当前时间戳,表示递增;如果有数据,说明已点赞,此时取消点赞,数据库对应字段-1,并且将用户id从redis中移除。


2. 排行榜功能实现

在笔记的详情页面,应该把给该笔记点赞的人显示出来,比如最早点赞的TOP5,形成点赞排行榜:

image-20230131150514923

按照点赞顺序,将用户的头像先后展示。


2.1 需求

需求:按照点赞时间先后排序,返回Top5的用户

ListSetSortedSet
排序方式按添加顺序排序无法排序根据score值排序
唯一性不唯一唯一唯一
查找方式按索引查找 或首尾查找根据元素查找根据元素查找

2.2 实现步骤

实现步骤:

  1. 去redis中查询top5的点赞用户
  2. 解析出其中的用户id
  3. 根据用户id去数据库查询用户

2.3 思路分析

没啥思路需要理清,很清晰。


2.4 代码实现

代码如下:

@Override
public Result queryBlogLikes(Long id) {String key = BLOG_LIKED_KEY + id;//1.查询top5的点赞用户 zrange key 0 4Set top5 = stringRedisTemplate.opsForZSet().range(key, 0, 4);if (top5 == null || top5.isEmpty()) {return Result.ok(Collections.emptyList());}//2.解析出其中的用户idList ids = top5.stream().map(Long::valueOf).collect(Collectors.toList());String idStr = StrUtil.join(",", ids);//3.根据用户id查询用户 WHERE id IN (5,1) ORDER BY FIELD(id,5,1)List userDTOS = userService.lambdaQuery().in(User::getId, ids).last("ORDER BY FIELD(id," + idStr + ")").list().stream().map(user -> BeanUtil.copyProperties(user, UserDTO.class)).collect(Collectors.toList());return Result.ok(userDTOS);
}

2.5 逻辑解析

代码逻辑:我们在实现点赞功能时,score值存储的是当前时间戳,一定是递增的,所以用户id的存储顺序也是按照时间先后顺序存储的。于是我们直接采用 range 方法得到前五个点赞用户的id。然后去到数据库中查询这前五个用户的信息,在查询语句中加上 ORDER BY FIELD(id,5,1) 是因为如果不加的话会按照id的数值大小依次返回用户数据,这样就无法实现排行榜的功能了。


3. 分页功能实现

我们已经实现了点赞功能和点赞排行榜功能,现在我们需要进一步改进分页功能。

3.1 需求

需求:按照点赞数量的多少进行分页查询,点赞量多的排在前面,点赞量少的排在后面。


3.2 实现步骤

实现步骤:

  1. 根据笔记的点赞量倒序排序并分页
  2. 获取当前页的数据
  3. 查询每条数据对应的用户信息和点赞信息

3.3 代码实现

代码如下:

@Override
public Result queryHotBlog(Integer current) {// 根据用户查询Page page = query().orderByDesc("liked").page(new Page<>(current, SystemConstants.MAX_PAGE_SIZE));// 获取当前页数据List records = page.getRecords();// 查询用户records.forEach(blog -> {this.queryBlogUser(blog);this.isBlogLiked(blog);});return Result.ok(records);
}private void queryBlogUser(Blog blog) {Long userId = blog.getUserId();User user = userService.getById(userId);blog.setName(user.getNickName());blog.setIcon(user.getIcon());
}private void isBlogLiked(Blog blog) {//1.获取当前用户UserDTO user = UserHolder.getUser();if (user == null) {return;}Long userId = user.getId();//2.判断当前用户是否已经点赞String key = "blog:liked:" + blog.getId();Double score = stringRedisTemplate.opsForZSet().score(key, userId.toString());blog.setIsLike(score != null);
}

3.4 逻辑解析

代码逻辑:如果已经看懂了前两个功能的实现,那么分页功能的逻辑也就明白了。

相关内容

热门资讯

北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...
世界上最漂亮的人 世界上最漂亮... 此前在某网上,选出了全球265万颜值姣好的女性。从这些数量庞大的女性群体中,人们投票选出了心目中最美...