使用redis完成文章点赞功能

要求

  1. 同一篇文章,只能点赞一次. 再次点赞后取消点赞.
  2. 文章下显示点过赞的用户列表.

使用redis完成文章点赞功能_第1张图片

思路

  1. 点赞 & 取消点赞
    1. 使用set将 文章key 用户id 保存在redis中.
    2. 请求进来后查询redis中是否存在, 如果存在, redis 移除, 数据库数量 -1; 反之 加1.
  2. 文章下统计点赞列表,并按照时间排序

    使用zset. 存入时 把当前时间当作score保存.
    取数据时可以按照range取出区间.
    拿到用户id列表后, 查询数据库中对应信息, 可以用 sort field 对字段中的数据进行排序.

相关代码

  1. 点赞 & 取消点赞
 public Result likeBlog(Long id) {
        UserDTO userDTO = UserHolder.getUser();
        if (userDTO == null) {
            return Result.fail("用户未登录");
        }
        String userId = userDTO.getId().toString();
        //查询用户是否点赞.
        Double score = stringRedisTemplate.opsForZSet().score(BLOG_LIKED_KEY + id, userId);
        //已经点赞
        if (Objects.nonNull(score)) {
            LambdaUpdateWrapper<Blog> updateWrapper = new LambdaUpdateWrapper<Blog>().eq(Blog::getId, id).setSql("liked=liked-1");
            boolean update = this.update(updateWrapper);
            if (update) {
                stringRedisTemplate.opsForZSet().remove(BLOG_LIKED_KEY + id, userId);
            }
            return Result.ok();
        }
        //没点赞
        LambdaUpdateWrapper<Blog> updateWrapper = new LambdaUpdateWrapper<Blog>().eq(Blog::getId, id).setSql("liked=liked+1");
        boolean update = this.update(updateWrapper);
        if (update) {
            stringRedisTemplate.opsForZSet().add(BLOG_LIKED_KEY + id, userId, System.currentTimeMillis());
        }
        return Result.ok();
    }


2. 文章显示点赞列表

```java
 /**
     * 查找给文章点赞的用户列表
     *
     * @param id
     * @return
     */
    @Override
    public Result likesBlogUsers(Long id) {
        //获取最先点赞的5个人
        Set<String> stringSet = stringRedisTemplate.opsForZSet().range(BLOG_LIKED_KEY + id, 0, 4);
        if (stringSet == null || stringSet.size() == 0) {
            return Result.ok(Collections.emptyList());
        }
        List<Long> ids = stringSet.stream().map(Long::valueOf).collect(Collectors.toList());
        String idStr = StrUtil.join(",", ids);
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        wrapper.in(User::getId, ids).last("order by field (id," + idStr + ")");
        List<User> users = userService.list(wrapper);
        List<UserDTO> userDTOList = users.stream()
                .map(user -> BeanUtil.copyProperties(user, UserDTO.class))
                .collect(Collectors.toList());

        return Result.ok(userDTOList);
    }

参考资料

参考自黑马头条. 以上代码为demo阶段. 并未投入使用.

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