redis实现点赞排行榜

上篇博客在redis中使用的是set集合,但是发现他其实并不能够满足排行榜的功能,所以需要改变。redis实现点赞排行榜_第1张图片

在这里使用sortedSet更适合一点。 

  1. 通过 ZSCORE 命令获取 SortedSet 中存储的元素的相关的 SCORE 值。
  2. 通过 ZRANGE 命令获取指定范围内的元素。

 所以呢,进行点赞和点赞排行榜可以完美实现了。

主要思路:

1.因为要实现排序功能,所以set集合并不能满足,需要一个有权重的集合,也就是SortedSet.(采用时间戳来实现权重,最后根据时间戳来进行排序。)

2:从redis中拿到前5的用户id(拿到的是set集合)

List ids = top5.stream().map(Long::valueOf).collect(Collectors.toList());
可以转换成list集合来处理数据。

3:根据id查询数据库。

controller

@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);
    }

    @GetMapping("/likes/{id}")
    public Result queryBlogLikes(@PathVariable("id") String id) {
        return blogService.queryBlogLikes(id);
    }
}

service

@Service
public class BlogServiceImpl extends ServiceImpl implements IBlogService {

    @Autowired
    private IUserService userService;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    //点赞业务。
    @Override
    public Result likeBlog(Long id) {
        // 1、获取登录用户
        UserDTO user = UserHolder.getUser();
        // 2、判断当前登录用户是否已经点赞(redis)
        Double score = stringRedisTemplate.opsForZSet().score(RedisConstants.BLOG_LIKED_KEY + id, user.getId().toString());
        // 3、如果未点赞,可以点赞
        if (score == null) {
            // 3.1、数据库点赞数 +1
            boolean isSuccess = update().setSql("liked = liked + 1").eq("id", user.getId().toString()).update();
            if (isSuccess) {
                // 3.2、保存用户到 Redis 的 zset 集合,用时间戳来 代表 权重  zadd key value score
                stringRedisTemplate.opsForZSet().add(RedisConstants.BLOG_LIKED_KEY + id,
                        user.getId().toString(),
                        System.currentTimeMillis());
            }
            // 4、如果已点赞,取消点赞
        } else {
            // 4.1、数据库点赞数 -1
            boolean isSuccess = update().setSql("liked = liked - 1").eq("id", user.getId().toString()).update();
            if (isSuccess) {
                // 4.2、把用户从 Redis 的 zset 集合移除
                stringRedisTemplate.opsForZSet().remove(RedisConstants.BLOG_LIKED_KEY + id, user.getId().toString());
            }
        }
        return Result.ok();
    }

    //首页展示。
    @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);
    }

    //具体id展示。
    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();
        Double score = stringRedisTemplate.opsForZSet().score(key, userId.toString());
        blog.setIsLike(score != null);
    }

    @Override
    public Result queryBlogLikes(String id) {
        String key = RedisConstants.BLOG_LIKED_KEY + id;
        // 查询 top5 的点赞用户
        Set top5 = 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);
    }
}

你可能感兴趣的:(SpringBoot,redis,redis,数据库,缓存)