当前位置: 首页 > article >正文

关注、取关、Redis实现共同关注、 博客推送与分页查询

@Resource
    private StringRedisTemplate stringRedisTemplate;

    @Resource
    private IUserService userService;
    @Override
    public Result follow(Long followUserId, Boolean isFollow) {
        //1.获取登陆的用户
        Long userId = UserHolder.getUser().getId();
        //1.判断是关注还是取关
        if(isFollow){
            //关注,新增数据
            Follow follow = new Follow();
            follow.setUserId(userId);
            follow.setFollowUserId(followUserId);
            boolean isSuccess = this.save(follow);
            if(isSuccess){
                // 把关注用户的id,放入到redis的set集合 sadd userId followerUserId
                String key = "follows:" + userId;
                stringRedisTemplate.opsForSet().add(key, followUserId.toString());
            }
        }else {
            //取关,删除
            QueryWrapper<Follow> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("follow_user_id", followUserId).eq("user_id", userId);
            boolean isSuccess = this.remove(queryWrapper);
            if(isSuccess){
                //从redis集合中移除
                String key = "follows:" + userId;
                stringRedisTemplate.opsForSet().remove(key, followUserId.toString());
            }

        }
        return Result.ok();
    }

    @Override
    public Result isFollow(Long followUserId) {
        //1.获取登陆的用户
        Long userId = UserHolder.getUser().getId();
        //查询是否关注
        Integer count = this.query().eq("follow_user_id", followUserId).eq("user_id", userId).count();
        return Result.ok(count > 0);
    }

    @Override
    public Result followCommons(Long id) {
        //获取当前的用户
        Long userId = UserHolder.getUser().getId();
        //知道两个用户在Redis中求交集
        String key1 = "follows:" + userId;
        String key2 = "follows:" + id;
        Set<String> intersect = stringRedisTemplate.opsForSet().intersect(key1, key2);
        if(intersect == null || intersect.isEmpty()){
            //无交集
            return Result.ok(Collections.emptyList());
        }
        //通过Set集合解析出Id集合
        List<Long> ids = intersect.stream().map(Long::valueOf).collect(Collectors.toList());
        //查询用户
        List<UserDTO> users = userService.listByIds(ids)
                .stream()
                .map(user -> BeanUtil.copyProperties(user, UserDTO.class))
                .collect(Collectors.toList());
        return Result.ok(users);
    }

 博客推送与分页查询

 查询的控制层

    @GetMapping("/of/follow")
    public Result queryBlogOfFollow(@RequestParam("lastId") Long max, @RequestParam(value = "offset", defaultValue = "0") Integer offset){
        return blogService.queryBlogOfFollow(max, offset);
    }

 发布与查询的服务层

    //大V发布,并进行推送
    @Override
    public Result saveBlog(Blog blog) {
        // 获取登录用户
        UserDTO user = UserHolder.getUser();
        blog.setUserId(user.getId());
        // 保存探店博文
        boolean isSuccess = this.save(blog);
        if(!isSuccess){
            return Result.fail("新增笔记失败");
        }
        //查询笔记作者的所有粉丝  follow_user_id时大V的id
        List<Follow> follows = followService.query().eq("follow_user_id", user.getId()).list();
        //推送笔记id给所有粉丝
        for (Follow follow : follows) {
            //获取粉丝id
            Long userId = follow.getUserId();
            //推送
            String key = "feed:" + userId;
            stringRedisTemplate.opsForZSet().add(key, blog.getId().toString(), System.currentTimeMillis());
        }
        // 返回id
        return Result.ok(blog.getId());
    }

    //粉丝收到,并实现滚动分页查询
    @Override
    public Result queryBlogOfFollow(Long max, Integer offset) {
        //1.获取当前用户
        Long userId = UserHolder.getUser().getId();
        //2.查询收件箱  ZREVRANGEBYSCORE key max min limit offset count
        String key = FEED_KEY + userId;
        Set<ZSetOperations.TypedTuple<String>> typedTuples = stringRedisTemplate.opsForZSet()
                .reverseRangeByScoreWithScores(key, 0, max, offset, 2);
        //非空判断
        if(typedTuples == null || typedTuples.isEmpty()){
            return Result.ok();
        }
        //3.解析数据:blogId,minTime(时间戳)、offset
        List<Long> ids = new ArrayList<>(typedTuples.size());
        long minTime = 0;
        int os = 1; //最少为一个与最小一样
        for (ZSetOperations.TypedTuple<String> typedTuple : typedTuples) {
            //获取id
            ids.add(Long.valueOf(typedTuple.getValue()));
            //获取分数
            long time = typedTuple.getScore().longValue();
            if(time == minTime){
                os++;
            }else {
                minTime = time;
                os = 1;
            }
        }
        //4.根据id查询blog
        String idStr = StrUtil.join(",", ids);
        List<Blog> blogs = this.query().in("id", ids).last("ORDER BY FIELD(id," + idStr + ")").list();
        for (Blog blog : blogs) {
            //查询blog有关的用户
            this.queryBlogUser(blog);
            //查询blog是否被点赞
            this.isBlogLiked(blog);
        }
        //5.封装并返回
        ScrollResult r = new ScrollResult();
        r.setList(blogs);
        r.setOffset(os);
        r.setMinTime(minTime);
        return Result.ok(r);
    }


http://www.kler.cn/news/339225.html

相关文章:

  • YOLOv8实战TT100K中国交通标志检测【数据集+YOLOv8模型+源码+PyQt5界面】
  • 众数信科 AI智能体智慧文旅解决方案——禅宗大模型
  • No.5 笔记 | 网络端口协议概览:互联网通信的关键节点
  • C++游戏开发:探索与挑战
  • SpringSecurity实现自定义登录接口
  • Redis实战-优惠券秒杀
  • Java中对象和对象变量
  • 数据结构篇(绪论)
  • k8s 中存储之 NFS 卷
  • 老房装修换窗需要注意哪些方面?
  • 学习使用Cube软件
  • 简易CPU设计入门:取指令(四)
  • 【代码随想录Day37】动态规划Part06
  • 【C语言】指针和数组的内存使用详解
  • IIOT工业物联网的标准与互操作性—SunIOT
  • Redis面试篇1
  • 计算机网络:物理层 —— 信道复用技术
  • 20.Nginx动静分离原理与案例实现
  • 极端天气道路目标检测数据集 3400张 带标注 VOC YOLO 6类
  • Javascript-标准内置对象-值属性-globalThis-Infinity-Nan-undefined 手写实现globalThis功能