Redis笔记点赞排行榜的实现示例
来源:脚本之家
时间:2023-02-25 10:11:38 345浏览 收藏
从现在开始,我们要努力学习啦!今天我给大家带来《Redis笔记点赞排行榜的实现示例》,感兴趣的朋友请继续看下去吧!下文中的内容我们主要会涉及到点赞、Redis笔记等等知识点,如果在阅读本文过程中有遇到不清楚的地方,欢迎留言呀!我们一起讨论,一起学习!
一、发布探店笔记
探店笔记类似点评网站的评价,往往是图文结合。对应的表有两个
- 探店笔记表(主键、商户id、用户id、标题、文字、图片、探店文字描述、点赞数量、评论数量)
- 评价表(笔记的评价)
先上传图片请求一次保存图片接口,再点发布请求发布接口。这两个接口已经写好
二、实现查看笔记接口
BlogController
@RestController @RequestMapping("/blog") public class BlogController { @Resource private IBlogService blogService; @GetMapping("/hot") public Result queryHotBlog(@RequestParam(value = "current", defaultValue = "1") Integer current) { return blogService.queryHotBlog(current); } @GetMapping("/{id}") public Result queryBlogById(@PathVariable("id") String id){ return blogService.queryBlogById(id); } }
IBlogService
public interface IBlogService extends IService{ Result queryBlogById(String id); Result queryHotBlog(Integer current); }
BlogServiceImpl
@Service public class BlogServiceImpl extends ServiceImplimplements IBlogService { @Autowired private IUserService userService; @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(this::queryBlogUser); 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()); } @Override public Result queryBlogById(String id) { Blog blog = getById(id); if(blog == null){ return Result.fail("笔记不存在!"); } queryBlogUser(blog); return Result.ok(blog); } }
三、点赞功能
现在已经写好的点赞接口
问题:这样写接口,可以一直按点赞重复点赞
需求
- 同一个用户只能点赞一次,再次点赞则取消点赞
- 如果当前用户已经点赞,则点赞按钮高亮显(前端已经实现,判断blog类的isLike属性)
实现步骤
- 给Blog类中添加一个isLike字段,表示是否被当前用户点赞
- 修改点赞功能,利用redis的set集合判断用户是否赞过,未赞则点赞数+1,赞过则-1
- 修改根据id查询blog的业务,判断当前用户是否点赞过,赋值给isLike字段
- 修改分页查询blog业务,判断当前用户是否赞过,赋值isLike字段
业务实现
@RestController @RequestMapping("/blog") public class BlogController { @Resource private IBlogService blogService; @PutMapping("/like/{id}") public Result likeBlog(@PathVariable("id") Long id) { return blogService.likeBlog(id); } @GetMapping("/hot") public Result queryHotBlog(@RequestParam(value = "current", defaultValue = "1") Integer current) { return blogService.queryHotBlog(current); } @GetMapping("/{id}") public Result queryBlogById(@PathVariable("id") String id){ return blogService.queryBlogById(id); } }
编写完点赞操作的接口后还要修改之前的查询接口,增加查询是否已经点赞
@Service public class BlogServiceImpl extends ServiceImplimplements IBlogService { @Autowired private IUserService userService; @Autowired private StringRedisTemplate stringRedisTemplate; @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); } @Override public Result likeBlog(Long id) { // 1、获取登录用户 UserDTO user = UserHolder.getUser(); // 2、判断当前登录用户是否已经点赞 Boolean isMember = stringRedisTemplate.opsForSet().isMember(RedisConstants.BLOG_LIKED_KEY + id, user.getId().toString()); if(BooleanUtil.isFalse(isMember)) { // 3、如果未点赞,可以点赞 // 3.1、数据库点赞数 +1 boolean isSuccess = update().setSql("liked = liked+1").eq("id", id).update(); // 3.2、保存用户到 Redis 的 set 集合 if(isSuccess){ stringRedisTemplate.opsForSet().add(RedisConstants.BLOG_LIKED_KEY + id, user.getId().toString()); } } else { // 4、如果已点赞,取消点赞 // 4.1、数据库点赞数 -1 boolean isSuccess = update().setSql("liked = liked - 1").eq("id", id).update(); // 4.2、把用户从 Redis 的 set 集合移除 if(isSuccess){ stringRedisTemplate.opsForSet().remove(RedisConstants.BLOG_LIKED_KEY + id, user.getId().toString()); } } return Result.ok(); } private void queryBlogUser(Blog blog) { Long userId = blog.getUserId(); User user = userService.getById(userId); blog.setName(user.getNickName()); blog.setIcon(user.getIcon()); } @Override public Result queryBlogById(String id) { Blog blog = getById(id); if(blog == null){ return Result.fail("笔记不存在!"); } queryBlogUser(blog); // 查询 Blog 是否被点赞 isBlogLiked(blog); return Result.ok(blog); } private void isBlogLiked(Blog blog) { Long userId = blog.getUserId(); String key = RedisConstants.BLOG_LIKED_KEY + blog.getId(); Boolean isMember = stringRedisTemplate.opsForSet().isMember(key, userId.toString()); blog.setIsLike(BooleanUtil.isTrue(isMember)); } }
四、点赞排行榜
查出给这个笔记点赞的人,类似微信朋友圈的点赞,可以展示谁点赞了,而且我们要进行排序
所以我们得用SortedSet这种数据类型
1、修改点赞逻辑
把原本存入set改为存入zset多加个分数,分数就是时间戳
@Override public Result likeBlog(Long id) { // 1、获取登录用户 UserDTO user = UserHolder.getUser(); // 2、判断当前登录用户是否已经点赞 Double score = stringRedisTemplate.opsForZSet().score(RedisConstants.BLOG_LIKED_KEY + id, user.getId().toString()); if(score == null) { // 3、如果未点赞,可以点赞 // 3.1、数据库点赞数 +1 boolean isSuccess = update().setSql("liked = liked+1").eq("id", id).update(); // 3.2、保存用户到 Redis 的 set 集合 if(isSuccess){ // 时间作为 key 的 score stringRedisTemplate.opsForZSet().add(RedisConstants.BLOG_LIKED_KEY + id, user.getId().toString(), System.currentTimeMillis()); } } else { // 4、如果已点赞,取消点赞 // 4.1、数据库点赞数 -1 boolean isSuccess = update().setSql("liked = liked - 1").eq("id", id).update(); // 4.2、把用户从 Redis 的 set 集合移除 if(isSuccess){ stringRedisTemplate.opsForZSet().remove(RedisConstants.BLOG_LIKED_KEY + id, user.getId().toString()); } } return Result.ok(); }
然后是否被点赞的方法也要修改,根据key取出分数,分数不为null就是点赞过了
private void isBlogLiked(Blog blog) { UserDTO user = UserHolder.getUser(); if(user == null){ return; } Long userId = user.getId(); String key = RedisConstants.BLOG_LIKED_KEY + blog.getId(); Double score = stringRedisTemplate.opsForZSet().score(key, userId.toString()); blog.setIsLike(score != null); }
2、点赞排行榜功能
需求:实现前五个点赞的用户返回
我们先用动态id去redis中查询出前五个点赞用户的id
然后根据id去数据库中查询信息封装到dto再返回
@GetMapping("/likes/{id}") public Result queryBlogLikes(@PathVariable("id") String id) { return blogService.queryBlogLikes(id); }
@Override public Result queryBlogLikes(String id) { String key = RedisConstants.BLOG_LIKED_KEY + id; // 查询 top5 的点赞用户 Settop5 = stringRedisTemplate.opsForZSet().range(key, 0, 4); if(top5 == null){ return Result.ok(Collections.emptyList()); } // 解析出其中的用户id List ids = top5.stream().map(Long::valueOf).collect(Collectors.toList()); String join = StrUtil.join(",", ids); // 根据用户id查询用户 List userDTOS = userService.query().in("id", ids).last("order by filed(id, "+join+")").list() .stream() .map(user -> BeanUtil.copyProperties(user, UserDTO.class)) .collect(Collectors.toList()); return Result.ok(userDTOS); }
注意:如果我们mp直接用in来查询根本不能保证点赞的顺序,因为in查询出来的是按照id顺序返回的,没有排序,我们要按照查询id的顺序来查,order by field(id,5,1)这样
本篇关于《Redis笔记点赞排行榜的实现示例》的介绍就到此结束啦,但是学无止境,想要了解学习更多关于数据库的相关知识,请关注golang学习网公众号!
-
342 收藏
-
361 收藏
-
159 收藏
-
164 收藏
-
221 收藏
-
156 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 立即学习 542次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 立即学习 507次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 立即学习 497次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 立即学习 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 立即学习 484次学习