Redis实战篇(五)好友关注

news2025/1/17 0:58:25

1、点赞 ------------ Set
2、点赞排行 ------SortedSet
3、共同关注 -------set sinter

一、共同关注

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

二、关注推送(Feed流)

关注推送也叫Feed流,直译为投喂。为用户持续的提供沉浸式的体验,通过无限下拉刷新获取新的信息。

TimeLine智能排序
定义不做内容筛选,简单的按照内容发布时间排序,常用于好友或关注利用智能算法屏蔽违规的、用户不感兴趣的内容
优点信息全面,不会有缺失。并且实现也相对简单投喂用户感兴趣信息,用户粘度很高
缺点信息噪音很多,用户不一定感兴趣,内容获取效率低如果算法不精准,可能起到反效果

1、Feed流的实现方式

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

拉模式推模式推拉结合
写比例
读比例
用户读取延迟
实现难度复杂简单很复杂
使用场景很少使用用户量少,没有大V过千万的用户量,有大V

2、Feed分页问题

Feed流中的数据会不断更新,所以数据的角标也在变化,因此不能采用传统的分页模式。采用滚动分页。
在这里插入图片描述
在这里插入图片描述
推送粉丝收件箱

    @Override
    public Result saveBlog(Blog blog) {
        // 1.获取登录用户
        UserDTO user = UserHolder.getUser();
        blog.setUserId(user.getId());
        // 2.保存探店笔记
        boolean isSuccess = save(blog);
        if(!isSuccess){
            return Result.fail("新增笔记失败!");
        }
        // 3.查询笔记作者的所有粉丝 select * from tb_follow where follow_user_id = ?
        List<Follow> follows = followService.query().eq("follow_user_id", user.getId()).list();
        // 4.推送笔记id给所有粉丝
        for (Follow follow : follows) {
            // 4.1.获取粉丝id
            Long userId = follow.getUserId();
            // 4.2.推送
            String key = FEED_KEY + userId;
            stringRedisTemplate.opsForZSet().add(key, blog.getId().toString(), System.currentTimeMillis());
        }
        // 5.返回id
        return Result.ok(blog.getId());
    }

(3)滚动分页

滚动分页:
max:当前时间戳 | 上一次查询的最小时间戳
min:0
offset : 0 | 在上一次的结果中,与最小值一样的元素个数
count: 5

@Data
public class ScrollResult {
    private List<?> list;
    private Long minTime;
    private Integer offset;
}
    @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);
        // 3.非空判断
        if (typedTuples == null || typedTuples.isEmpty()) {
            return Result.ok();
        }
        // 4.解析数据:blogId、minTime(时间戳)、offset
        List<Long> ids = new ArrayList<>(typedTuples.size());
        long minTime = 0; // 2
        int os = 1; // 2
        for (ZSetOperations.TypedTuple<String> tuple : typedTuples) { // 5 4 4 2 2
            // 4.1.获取id
            ids.add(Long.valueOf(tuple.getValue()));
            // 4.2.获取分数(时间戳)
            long time = tuple.getScore().longValue();
            if(time == minTime){
                os++;
            }else{
                minTime = time;
                os = 1;
            }
        }

        // 5.根据id查询blog
        String idStr = StrUtil.join(",", ids);
        List<Blog> blogs = query().in("id", ids).last("ORDER BY FIELD(id," + idStr + ")").list();

        // 6.封装并返回
        ScrollResult r = new ScrollResult();
        r.setList(blogs);
        r.setOffset(os);
        r.setMinTime(minTime);

        return Result.ok(r);
    }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/23941.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Gradle (史上最全): 5W字文

Gradle是绕不开的一个构建工具 对于用惯了 maven的人来说&#xff0c; Graddle不好用&#xff0c; 非常不好用&#xff0c; 主要是环境 会遇到各种各样的问题 但是&#xff0c;越来越多的 场景使用到了 Graddle&#xff0c;但是 spring 的源码&#xff0c;使用 Gradle 构建 …

【Fiddler】安卓7.0以上添加Fiddler/Charles证书到系统根证书(模拟器-雷电)

目录 一、安装工具 1、安装open-ssl 2、配置环境变量 3、验证安装 二、Fiddler 1、导出证书 2、转化cer格式变成PEM 3、查看PEM的哈希值 三、Charles 1、导出证书 2、查看PEM的哈希值 四、证书安装到安卓模拟器 &#xff08;雷电&#xff09; 1、使用模拟器的adb命令 2、…

【实战案例】——实战渗透某不法网站

作者名&#xff1a;Demo不是emo 主页面链接&#xff1a;主页传送门 创作初心&#xff1a;舞台再大&#xff0c;你不上台&#xff0c;永远是观众&#xff0c;没人会关心你努不努力&#xff0c;摔的痛不痛&#xff0c;他们只会看你最后站在什么位置&#xff0c;然后羡慕或鄙夷座…

RPA-机器人流程自动化

RPA-机器人流程自动化RPA-机器人流程自动化简介RPA是什么&#xff1f;RPA历史上的演变RPA原理RPA特点RPA技术框架及功能1.TagUI2.RPA for Python3.Robot Framework4.Automagica5.Taskt6.OpenRPARPA部署模式1 环境配置的参数调整2 将自动化程序整体打包部署3 版本的管理和控制机…

【微服务】SpringCloud的OpenFeign与Ribbon配置

&#x1f496; Spring家族及微服务系列文章 ✨【微服务】SpringCloud轮询拉取注册表及服务发现源码解析 ✨ 【微服务】SpringCloud微服务续约源码解析 ✨ ✨【微服务】SpringCloud微服务注册源码解析 ✨【微服务】Nacos2.x服务发现&#xff1f;RPC调用&#xff1f;重试机制&…

token的使用

一&#xff1a;什么是token及token的作用&#xff1f; 1.什么是token&#xff1f; Token是首次登录时&#xff0c;由服务器下发&#xff0c;作为客户端进行请求时的一个令牌。当请求后台方法时&#xff0c;用于身份验证 当第一次登录后&#xff0c;服务器生成一个Token便将此…

1013 Battle Over Cities

目录 Input Specification: Output Specification: Sample Input: Sample Output: 一、题目大意 二、思路 三、代码 It is vitally important to have all the cities connected by highways in a war. If a city is occupied by the enemy, all the highways from/to…

138.深度学习分布式计算框架-1

138.1 PaddlePaddle PaddlePaddle是百度开源的一个深度学习平台PaddlePaddle为深度学习研究人员提供了丰富的API&#xff0c;可以轻松地完成神经网络配置&#xff0c;模型训练等任务。官方文档中简易介绍了如何使用框架在 线性回归识别数字图像分类词向量个性化推荐情感分析语…

2.14 分享9个高吸睛小红书首图制作技巧,要认真学哦!【玩赚小红书】

在小红书里&#xff0c;推荐的图片比例是3:4、1:1、4:3。 做图的时候就要提前调整好比例&#xff0c;免得上传被自动裁剪掉重要信息。竖屏最常用&#xff0c;因为比较“霸屏”&#xff0c;展现的信息空间比较大。当然&#xff0c;选哪个比例还是看个人偏好&#xff0c;尽量保持…

2022年C++面试题万余字汇总【面试官常问】

2022年C面试题【常问重点问题】1、请你说说 GET 和 POST 的区别&#xff1f;2、简述一下 C 中的多态?3、说一说进程有多少种状态&#xff0c;如何转换?3、请你说说指针和引用的区别4、简述一下虚函数的实现原理5、说一说 vector 和 list 的区别&#xff0c;分别适用于什么场景…

剪映PC版英文字幕翻译最新方法(中英互译)

原文地址 剪映PC版英文字幕翻译最新方法&#xff08;中英互译&#xff09; – 方包博客 – java|python|前端开发|运维|电商|ui设计剪映PC版英文字幕翻译最新方法&#xff08;中英互译&#xff09;https://www.fang1688.cn/ziyuan/3431.html 我的是剪映 v3.3.0版本。旧版不支持…

Omorn - NJ301-1100 AND NX102-9000 - CIP - UCMM 通讯

目录 Omorn - NJ301-1100 AND NX102-9000 - CIP - UCMM 通讯 测试案例IP 创建变量类型 指令编写加数据测试 Omorn - NJ301-1100 AND NX102-9000 - CIP - CLASS3 通讯 Omorn - NJ301-1100 AND NX102-9000 - CIP - UCMM 通讯 说明&#xff1a; 1、NJ的网络通讯指令要有CIP…

【C语言入门数据结构】顺序表

&#x1f648;个人主页&#xff1a;阿伟t &#x1f449;系列专栏&#xff1a;【C语言–大佬之路】 &#x1f388;今日心语&#xff1a;你所看到的惊艳&#xff0c;都曾被平庸所历练。 前言&#xff1a;继【时间复杂度和空间复杂】度之后&#xff0c;本章我们来介绍数据结构中…

docker能干什么以及基本名词解释

docker能干什么以及基本名词解释 docker能干什么&#xff1f;比较docker和虚拟机的不同DEVOps (开发&#xff0c;运维)基本名词解释docker能干什么&#xff1f; 比较docker和虚拟机的不同 传统虚拟机&#xff0c;虚拟出一条硬盘&#xff0c;然后再这个系统上安装和运行软件。…

1.3-1.7 测度理论

测度理论 (Durrett) 第五版 个人笔记 答案 Durrett高等概率论教材 (Probability) 攻读概率及统计/机器学习应用方向博士学位. 1. Measure Theory Probability SpacesDistributionsRandom VariablesIntegrationProperties of the IntegralExpected ValueProduct Measures, Fub…

python实现科研通定时自动签到

1 新建虚拟环境 python -m venv venv2 激活环境 3 官网下载edgedriver.exe Edge WebDriver链接在此&#xff0c;下载对应的浏览器的版本&#xff0c;然后改名为msedgedriver.exe放在\venv\Scripts下面。 main.py代码如下&#xff1a; from selenium import webdriver from…

动态规划——完全背包问题(C++实现)

题目描述&#xff1a; 问题分析&#xff1a; 完全背包问题和01背包问题的不同点&#xff1a; 简单01背包中是从N个物品里选&#xff0c;每个物品只能用1次&#xff0c;完全背包则不同&#xff0c;每个物品可以用无限次。 01背包&#xff1a; 如果物品能放入背包&#xff08…

PIC单片机1——按钮测试

#include "p18f458.h" #define Button PORTBbits.RB0 #define Led PORTCbits.RC0 void delay() { unsigned char i,j; for(i0;i<255;i) for(j0;j<255;j) ; } void main() { TRISBbits.TRISB01;//B0输入 TRISCbits.TRISC00;//C0输出 Led1;…

[计算机毕业设计]大数据疫情分析与可视化系统

前言 &#x1f4c5;大四是整个大学期间最忙碌的时光,一边要忙着准备考研,考公,考教资或者实习为毕业后面临的就业升学做准备,一边要为毕业设计耗费大量精力。近几年各个学校要求的毕设项目越来越难,有不少课题是研究生级别难度的,对本科同学来说是充满挑战。为帮助大家顺利通过…

Unload data from Databend | 新手篇(4)

上篇我们讲了怎么利用 copy 命令借助于 Stage 把数据加载到 Databend 中&#xff0c;Databend 致力于构建一个完整的数据湖&#xff0c;也需要支持用户把数据从 Databend 中取走&#xff0c;这里 Databend 给三种可以把数据取走的办法&#xff1a; External table 把数据存储在…