Content

Redis笔记点赞排行榜的实现示例(redis 点赞功能设计)居然可以这样

文章摘要

这篇文章介绍了如何在探店笔记系统中实现点赞功能及其排行榜的展示。文章详细描述了以下核心内容: 1. **探店笔记表与评价表设计**:探店笔记表包含笔记信息、点赞数量、评论数量等字段,评价表用于存储用户对笔记的评论。 2. **点赞功能实现**: - 创建点赞接口,支持用户对笔记的点赞和取消点赞操作。 - 使用Redis的集合和有序集合(ZSet)来管理点赞记录,确保点赞的增删操作高效且支持排序。 3. **点赞排行榜实现**: - 利用Redis的有序集合(ZSet)记录点赞时间戳,实现按时间排序的点赞排行榜。 - 通过Redis的score方法获取用户的点赞时间戳,判断是否已经点赞。 4. **用户信息展示**: - 将点赞记录中的用户ID与用户表关联,返回包含点赞用户信息的DTO,提升用户界面的友好性。 文章还提到,使用Redis的有序集合(ZSet)支持动态获取前五位点赞用户,并结合用户ID进行查询和排序,最终返回用户信息。这种实现不仅高效,而且符合实时排行榜的需求。


目录一、发布探店笔记二、实现查看笔记接口三、点赞功能四、点赞排行榜 1、修改点赞逻辑2、点赞排行榜功能

探店笔记类似点评网站的评价,往往是图文结合。对应的表有两个

探店笔记表(主键、商户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<Blog> { Result queryBlogById(String id); Result queryHotBlog(Integer current); }

BlogServiceImpl

@Service public class BlogServiceImpl extends ServiceImpl<BlogMapper, Blog> implements IBlogService { @Autowired private IUserService userService; @Override public Result queryHotBlog(Integer current) { // 根据用户查询 Page<Blog> page=query() .orderByDesc(“liked”) .page(new Page<>(current, SystemConstants.MAX_PAGE_SIZE)); // 获取当前页数据 List<Blog> 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 ServiceImpl<BlogMapper, Blog> implements IBlogService { @Autowired private IUserService userService; @Autowired private StringRedisTemplate stringRedisTemplate; @Override public Result queryHotBlog(Integer current) { // 根据用户查询 Page<Blog> page=query() .orderByDesc(“liked”) .page(new Page<>(current, SystemConstants.MAX_PAGE_SIZE)); // 获取当前页数据 List<Blog> 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这种数据类型

把原本存入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); }

需求:实现前五个点赞的用户返回

我们先用动态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 的点赞用户 Set<String> top5=stringRedisTemplate.opsForZSet().range(key, 0, 4); if(top5==null){ return Result.ok(Collections.emptyList()); } // 解析出其中的用户id List<Long> ids=top5.stream().map(Long::valueOf).collect(Collectors.toList()); String join=StrUtil.join(“,”, ids); // 根据用户id查询用户 List<UserDTO> 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笔记点赞排行榜的实现示例的文章就介绍到这了,更多相关Redis笔记点赞内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:使用Redis实现用户积分排行榜的教程redis实现排行榜的简单方法利用redis实现排行榜的小秘诀redis实现排行榜功能使用Redis实现实时排行榜功能手把手教你使用redis实现排行榜功能