Redis实现好友功能

好友功能是目前社交场景的必备功能之一,一般好友相关的功能包含有:关注/取关、我(他)的关注、我(他)的粉丝、共同关注等这样一些功能。

1.关注和取关

1.设计思路

总体思路我们采用MySQL + Redis的方式结合完成。MySQL主要是保存落地数据,而利用Redis的Sets进行集合操作。Sets拥有去重(我们不能多次关注同一用户)功能**。一个用户我们存贮两个集合:一个是保存用户关注的人 另一个是保存关注用户的人.**

1.1 用到的命令
  • SADD 添加成员;命令格式: SADD key member [member …] ----- 关注
  • SREM 移除某个成员;命令格式: SREM key member [member …] -------取关
  • SCARD 统计集合内的成员数;命令格式: SCARD key -------关注/粉丝个数
  • SISMEMBER 判断是否是集合成员;命令格式:SISMEMBER key member ---------判断是否关注(如果关注那么只可以点击取关)
  • SMEMBERS 查询集合内的成员;命令格式: SMEMBERS key -------列表使用(关注列表和粉丝列表)
  • SINTER 查询集合的交集;命令格式: SINTER key [key …] --------共同关注、我关注的人关注了他

2.关注表结构

CREATE TABLE `t_follow` (
`id`  int(11) NOT NULL AUTO_INCREMENT ,
`diner_id`  int(11) NULL DEFAULT NULL COMMENT '用户id' ,
`follow_diner_id`  int(11) NULL DEFAULT NULL COMMENT '用户关注的人id' ,
`is_valid`  tinyint(1) NULL DEFAULT NULL COMMENT '是否关注,0未关注/取消关注,1已关注',
`create_date`  datetime NULL DEFAULT NULL ,
`update_date`  datetime NULL DEFAULT NULL ,
PRIMARY KEY (`id`)
)
ENGINE=InnoDB
DEFAULT CHARACTER SET=utf8 COLLATE=utf8_general_ci
AUTO_INCREMENT=6
ROW_FORMAT=COMPACT;

为什么t_follow要使用is_valid标识符?

答:当用户A第一次关注用户B时,会往t_follow表添加一条数据,此时 is_valid值为1,当A取消对B的关注时,不需要删除刚刚插入的数据,只需要更改is_valid变成0即可。当然也可以不用is_valid字段,当A取消对B的关注时,物理删除对应的这条数据,但公司一般删除不会做物理删除。

3.关注/取关业务逻辑

@Service
public class FollowService {@Value("${service.name.ms-oauth-server}")private String oauthServerName;@Resourceprivate RestTemplate restTemplate;@Resourceprivate FollowMapper followMapper;@Resourceprivate RedisTemplate redisTemplate;/*** 关注/取关** @param followDinerId 关注的食客ID* @param isFollowed    是否关注 1=关注 0=取消* @param accessToken   登录用户token* @param path          访问地址* @return*/@Transactional(rollbackFor = Exception.class)public ResultInfo follow(Integer followDinerId, int isFollowed,String accessToken, String path) {// 是否选择了关注对象AssertUtil.isTrue(followDinerId == null || followDinerId < 1, "请选择要关注的人");// 获取登录用户信息SignInDinerInfo dinerInfo = loadSignInDinerInfo(accessToken);// 去关注表中查询看有没有对应数据Follow follow = followMapper.selectFollow(dinerInfo.getId(), followDinerId);// 如果没有关注信息,且要进行关注操作if (follow == null && isFollowed == 1) {// 添加关注信息int count = followMapper.save(dinerInfo.getId(), followDinerId);// 添加关注列表到 Redisif (count == 1) {addToRedisSet(dinerInfo.getId(), followDinerId);}return ResultInfoUtil.build(ApiConstant.SUCCESS_CODE,"关注成功", path, "关注成功");}// isValid值为0,那么是取关,如果isValid=1那么就是关注中// 如果有关注信息,且目前处于取关状态,且要进行关注操作if (follow != null && follow.getIsValid() == 0 && isFollowed == 1) {// 重新关注int count = followMapper.update(follow.getId(), isFollowed);// 添加关注列表if (count == 1) {addToRedisSet(dinerInfo.getId(), followDinerId);}return ResultInfoUtil.build(ApiConstant.SUCCESS_CODE,"关注成功", path, "关注成功");}// 如果有关注信息,且目前处于关注中状态,且要进行取关操作if (follow != null && follow.getIsValid() == 1 && isFollowed == 0) {// 取关int count = followMapper.update(follow.getId(), isFollowed);// 移除 Redis 关注列表removeFromRedisSet(dinerInfo.getId(), followDinerId);return ResultInfoUtil.build(ApiConstant.SUCCESS_CODE,"成功取关", path, "成功取关");}return ResultInfoUtil.buildSuccess(path, "操作成功");}/*** 添加关注列表到 Redis** @param dinerId* @param followDinerId*/
private void addToRedisSet(Integer dinerId, Integer followDinerId) {redisTemplate.opsForSet().add(RedisKeyConstant.following.getKey() + dinerId, followDinerId);redisTemplate.opsForSet().add(RedisKeyConstant.followers.getKey() + followDinerId, dinerId);
}/*** 移除 Redis 关注列表** @param dinerId* @param followDinerId*/
private void removeFromRedisSet(Integer dinerId, Integer followDinerId) {redisTemplate.opsForSet().remove(RedisKeyConstant.following.getKey() + dinerId, followDinerId);redisTemplate.opsForSet().remove(RedisKeyConstant.followers.getKey() + followDinerId, dinerId);
}}

2.共同关注列表

  • 从Redis中读取登录用户的关注列表与查看用户的关注列表,然后进行交集操作,获取共同关注的用户id
  • 然后通过用户id数据获取用户基本信息

1.查询共同好友代码

/*** 共同好友** @param dinerId* @param accessToken* @param path* @return*/
public ResultInfo findCommonsFriends(Integer dinerId, String accessToken, String path) {// 是否选择了关注对象AssertUtil.isTrue(dinerId == null || dinerId < 1, "请选择要查看的人");// 获取登录用户信息SignInDinerInfo dinerInfo = loadSignInDinerInfo(accessToken);// 登录用户的关注信息String loginDinerKey = RedisKeyConstant.following.getKey() + dinerInfo.getId();// 登录用户关注的对象的关注信息String dinerKey = RedisKeyConstant.following.getKey() + dinerId;// 计算交集Set<Integer> followingDinerIds = redisTemplate.opsForSet().intersect(loginDinerKey, dinerKey);// 没有if (followingDinerIds == null || followingDinerIds.isEmpty()) {return ResultInfoUtil.buildSuccess(path, new ArrayList<ShortDinerInfo>());}// 根据 ids 查询食客信息ResultInfo resultInfo = restTemplate.getForObject(dinersServerName + "findByIds?access_token=${accessToken}&ids={ids}",ResultInfo.class, accessToken, StrUtil.join(",", followingDinerIds));if (resultInfo.getCode() != ApiConstant.SUCCESS_CODE) {resultInfo.setPath(path);return resultInfo;}// 处理结果集List<LinkedHashMap> dinerInfoMaps = (ArrayList) resultInfo.getData();List<ShortDinerInfo> dinerInfos = dinerInfoMaps.stream().map(diner -> fillBeanWithMap(diner, new ShortDinerInfo(), true)).collect(Collectors.toList());return ResultInfoUtil.buildSuccess(path, dinerInfos);
}

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

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

相关文章

【Ant Design of Vue】Modal.confirm无法关闭的bug

一、问题 在使用 Ant Design Vue 的 Modal.confirm 确认框时&#xff0c;出现了点击取消和确定后 Modal.confirm 确认框无法关闭的问题 二、代码 代码完全是 copy 的官网的代码&#xff0c;但是 copy 到本地后就会出现上述问题 <template><a-button click"sho…

48-DOM节点,innerHTML,innerText,outerHTML,outerText,静态获取,单机click,cssText

1.DOM基础 Document Object Module,文档对象模型,window对象,document文档,都可以获取和操作 1)文档节点 2)属性节点(标签内的属性href,src) 3)文本节点(标签内的文字) 4)注释节点 5)元素节点(标签) 2.获取元素节点 2.1通过标签名获取getElementsByTagName() …

Python中HTTP代理的配置和使用

在Python中&#xff0c;HTTP代理是一种常用的技术&#xff0c;用于控制和修改HTTP请求和响应。通过使用HTTP代理&#xff0c;我们可以更好地控制网络请求的行为&#xff0c;提高安全性、隐私性和效率。下面我们将详细介绍如何在Python中配置和使用HTTP代理。 一、配置HTTP代理…

Unity 编辑器篇|(十一)Gizmos (全面总结 | 建议收藏)

目录 1. 前言2 参数总览3 Gizmos绘制3.1 立方体&#xff1a;DrawCube3.2 视锥&#xff1a;DrawFrustum3.3 贴图&#xff1a;DrawGUITexture3.4 图标&#xff1a;DrawIcon3.5 线段&#xff1a;DrawLine3.6 网格&#xff1a;DrawMesh3.7 射线&#xff1a;DrawRay3.8 球体&#xf…

寒假刷题-递归与递推

寒假刷题 92. 递归实现指数型枚举 解法1递归 使用递归对每一个坑位进行选择&#xff0c;每个坑位有两种选择&#xff0c;填或者不填&#xff0c;使用st数组来记录每个坑位的状态&#xff0c;u来记录已经有多少坑位有了选择。 每个坑位有2钟选择&#xff0c;n个坑位的复杂度就…

Java根据二叉树的先序和后序得到二叉树

一般情况下&#xff0c;我们会根据先序和后序写出二叉树&#xff0c;但是用代码怎末写呢&#xff1f; 例如&#xff1a; 给定两个整数数组 preorder 和 inorder &#xff0c;其中 preorder 是二叉树的先序遍历&#xff0c; inorder 是同一棵树的中序遍历&#xff0c;请构造二…

pdf怎么查看?6个不能错过的软件!

PDF&#xff0c;作为一种常用的文件格式&#xff0c;已经成为了我们工作、学习中的必备工具。然而&#xff0c;对于许多新手来说&#xff0c;如何查看和编辑PDF文件却是一个不小的挑战。今天&#xff0c;我们就来为大家详细介绍一下如何查看和编辑PDF文件&#xff0c;以及一些必…

01_泛型

文章目录 泛型泛型类泛型接口泛型方法泛型的通配泛型的擦除 泛型 参数化类型。 泛型的好处&#xff1a; 省去了类型强转的麻烦&#xff08;比如&#xff1a;Object类、interface接口等都需要类型强转&#xff09;将运行期遇到的问题转移到了编译期 泛型类 所谓泛型类, 就是…

Android Dialog setCanceledOnTouchOutside失效,点击dialog外面不消失

前言&#xff1a;有一个需求需要点击dialog外面要消失&#xff0c;本来以为很简单结果设置了一直未生效 setCanceledOnTouchOutside(true); 问了半天chat-gpt4结果给的答案都不明显 查看代码发现设置了style&#xff0c;于是尝试去除这个style&#xff0c;结果点击setCancele…

【c++】——栈or队列or优先级队列

目录 &#x1f393;容器适配器 &#x1f393;Stack栈 &#x1f6a9;Stack的介绍 &#x1f6a9;Stack的基本使用 &#x1f6a9;Stack底层实现 &#x1f393;queue队列 &#x1f6a9;queue的介绍 &#x1f6a9;queue的基本使用 &#x1f6a9;queue的底层实现 &#x1…

【C++】C++的IO流

一、C语言的输入与输出 C 语言中我们用到的最频繁的输入输出方式就是 scanf () 与 printf()。 scanf()&#xff1a;从标准输入设备&#xff08;键盘&#xff09;读取数据&#xff0c;并将值存放在变量中。printf()&#xff1a;将指定的文字/字符串输出到标准输出设备&#xff…

Java如何做到无感知刷新token含示例代码(值得珍藏)

1. 前言 在系统页面进行业务操作时&#xff0c;有时会突然遇到应用闪退&#xff0c;并被重定向至登录页面&#xff0c;要求重新登录。此问题的出现&#xff0c;通常与系统中用于存储用户ID和token信息的Redis缓存有关。具体来说&#xff0c;这可能是由于token过期所导致的身份…

容器部署的nextcloud配置onlyoffice时开启密钥

容器部署的nextcloud配置onlyoffice时开启密钥 配置 进入onlyoffice容器 docker exec -it 容器id bash编辑配置vi /etc/onlyoffice/documentserver/local.json enable设置为true&#xff0c;并配置secret 重启容器&#xff0c;并将配置的密钥填入nextcloud密钥页面 docker r…

复杂字幕特效SDK,重塑视频字幕新体验

字幕特效已经成为了提升视频品质、增强观众体验的重要手段。美摄科技作为行业领先的技术提供商&#xff0c;近期推出的复杂字幕特效SDK&#xff0c;更是引领了这一领域的创新潮流。 美摄科技复杂字幕特效SDK&#xff0c;不仅具备了电影级别的字幕功能&#xff0c;更实现了众多…

【全网最全】2024华数杯国际赛B题成品论文50页+1-4问高质量代码+完整数据集+建模过程+保姆级教学

基于数据分析下的光伏发电 摘 要&#xff08;完整版在文末&#xff09; 根据最新数据&#xff0c;中国的总发电量超过20万亿千瓦时&#xff0c;总体排名世界第一&#xff0c;而光伏发电是一种重要的可再生能源&#xff0c;可以将太阳能转化为电能可以减少对传统能源的依赖&…

VBA窗体跟随活动单元格【简易版】(2/2)

上一篇博客&#xff08;文章连接如下&#xff09;中使用工作表事件Worksheet_SelectionChange实现了窗体跟随活动单元格的动态效果。 VBA窗体跟随活动单元格【简易版】(1/2) 为了在用户滚动工作表窗体之后仍能够实现跟随效果&#xff0c;需要使用Application.Windows(1).Visibl…

归并排序详解

目录 ​&#x1f4a1;基本思想 &#x1f4a1;图文介绍 &#x1f4a1;动图演示 &#x1f4a1;过程解释 &#x1f4a1;代码实现 &#x1f4a1;递归实现 &#x1f4a1;非递归实现 &#x1f4a1;总结 &#x1f4a1;基本思想 归并排序&#xff08;MERGE-SORT&#xff09;是…

数据结构--串

本文为复习的草稿笔记&#xff0c;&#xff0c;&#xff0c;有点乱 1. 串的基本概念和基本操作 串是由零个或多个字符组成的有限序列 2. 串的存储结构 3.串的应用 模式匹配 BF算法&#xff08;简单匹配算法 穷举法 算法思路&#xff1a;从子串的每一个字符开始依次与主串…

深耕文档型数据库12载,SequoiaDB再开源

1月15日&#xff0c;巨杉数据库举行SequoiaDB新特性及开源项目发布活动。本次活动回顾了巨杉数据库深耕JSON文档型数据库12年的发展历程与技术演进&#xff0c;全面解读了SequoiaDB包括在高可用、安全、实时、易用性四个方向的技术特性&#xff0c;宣布了2024年面向技术社区的开…

无法打开浏览器开发者工具的可能解决方法

网页地址: https://jx.xyflv.cc/?url视频地址url 我在抖音里面抓了一个视频地址, 获取到响应的json数据, 找到里面的视频地址信息 这个网站很好用: https://www.jsont.run/ 可以使用js语法对json对象操作, 找到所有视频的url地址 打开网页: https://jx.xyflv.cc/?urlhttps:…