如何用Redis实现微博关注关系

在微博中,每一个用户都会有一个关注列表,一个粉丝列表。用户可以查看自己的关注,粉丝列表,也可以查看别人的关注,粉丝列表。并且,要展示列表里每个人与当前查看者的关注状态。

微博中,每一个用户都会有一个关注列表,一个粉丝列表。用户可以查看自己的关注,粉丝列表,也可以查看别人的关注,粉丝列表。并且,要展示列表里每个人与当前查看者的关注状态。

关注关系产生的四种关系状态

  • 关注
  • 粉丝
  • 双向关注(互粉)
  • 无关系

需求分析

在微博中,每一个用户都会有一个关注列表,一个粉丝列表。用户可以查看自己的关注,粉丝列表,也可以查看别人的关注,粉丝列表。并且,要展示列表里每个人与当前查看者的关注状态。状态的可能性就是上面讲到得四种关系状态。

问题可以分两种情况来看:

  1. 看自己的关注,粉丝列表
  2. 看别人的关注,粉丝列表

看自己的关注,粉丝列表:

这种情况相对简单一点。比如看自己的关注列表,列表里的人的与自己的关系状态不可能是“无关系”和“粉丝”。只可能是“关注”和“双向关注”。同样,粉丝列表也只有两种状态。

看别人的关注,粉丝列表:

这是最复杂的情况,假如看别人关注列表,列表里的人和自己可能有上述全部四种关系状态。

从集合的图来分析

如何用Redis实现微博关注关系

如上图所示。左边的圆表示用户的关注列表,右边的圆表示粉丝列表,下边的圆表示的是要查看的列表(集合)。分别用follow, fans, find来表明这三个集合。

当查看自己的列表时,其实表示find集合是上面集合中某一个的子集。例如查看自己粉丝,表示find是fans的子集,查看自己的关注,表示find是follow的子集。

查看别人的列表时,此时图中产生了三个集合的交集。要查询集合中的用户可能是在你的粉丝,关注集合中,也可能不在。就是说可能是任何一种关系状态,问题的根本就是,我们要计算出每一个用户与当前用户的关系状态。要求解四种关系状态,我们必然要求出图中下部分的三个小交集。

  • 要查询的集合与我的互粉交集
  • 要查询的集合与我的关注交集
  • 要查询的集的与我的粉丝交集

不在这三个小交集中的用户就是无关系状态的用户。

假如我们采用如下一套命名:

关注集合
follow:userID 粉丝集合 fans:userID

互粉集合(临时)
fofa:userID 要查询的集合(临时) find:userID

要查询的集合与我的关注交集(临时)
find_inter_follow:userID 要查询的集的与我的粉丝交集(临时) find_inter_fans:userID

要查询的集合与我的互粉交集(临时)
find_inter_fofa:userID

find中其他就是未关注

使用Sorted Set存储关系

score用来存储关注的时间,每个用户存储两个集合。follow:userID存储用户的关注,fans:userID存储用户的粉丝。于是我们可以设计一个函数来求出这些状态的集合。

函数返回:

  1. "findSet"=>$findSet,//要查询的集合
  2. "fofaSet"=>$fofaSet,//互粉的集合
  3. "findInterFollowSet"=>$findInterFollowSet,//要查询的集合与我的关注交
  4. "findInterFansSet"=>$findInterFansSet//要查询的集的与我的粉丝交

求出以上四个集合,就可以进行关系状态判断,先判断是否互粉,如果不是互粉,再判断是否是我关注的,如果不是,再判断是否是我的粉丝。如果都不是就是无关系。这样就能把状态求出来了。

  1. /*
  2. *userID:当前用户id
  3. *targetUserID:被查看的人的id
  4. *findType:查看的是哪个列表
  5. *findStart:分页查看的列表开始的位置
  6. *findEnd:分页查看的列表结束的位置
  7. */
  8. functiongetChunkSets($redis,$userID,$targetUserID,$findType,$findStart,$findEnd){
  9. $fansKey="fans:".$userID;
  10. $followKey="follow:".$userID;
  11. $findKey="find:".$userID;
  12. $targetKey=$findType.":".$targetUserID;
  13. $fofaKey="find_inter_fofa:".$userID;
  14. $findInterFollowKey="find_inter_follow:".$userID;
  15. $findInterFansKey="find_inter_fans:".$userID;
  16. //找出要查询的集合元素
  17. $findSet=$redis->zRevRange($targetKey,$findStart,$findEnd,TRUE);
  18. //要查询的集合与我的关注交
  19. $findInterFollowSet=array();
  20. //要查询的集的与我的粉丝交
  21. $findInterFansSet=array();
  22. //先清掉临时集合
  23. $redis->del($findKey);
  24. $redis->del($fofaKey);
  25. $redis->del($findInterFollowKey);
  26. $redis->del($findInterFansKey);
  27. //存起来
  28. foreach($findSetas$uid=>$score){
  29. $redis->zAdd($findKey,$score,$uid);
  30. }
  31. //求互粉集合
  32. if($userID!=$targetUserID){//看别人
  33. $redis->zInter($fofaKey,array($findKey,$fansKey,$followKey));
  34. /*
  35. *如果不是看自己的列表,还要求
  36. *1:要查询的集合与我的关注交
  37. *2:要查询的集的与我的粉丝交
  38. */
  39. $redis->zInter($findInterFollowKey,array($findKey,$followKey));
  40. $redis->zInter($findInterFansKey,array($findKey,$fansKey));
  41. $findInterFollowSet=$redis->zRevRange($findInterFollowKey,0,-1);
  42. $findInterFansSet=$redis->zRevRange($findInterFansKey,0,-1);
  43. }else{
  44. if($findType=="fans"){//自己看粉丝列表
  45. $redis->zInter($fofaKey,array($findKey,$followKey));
  46. }elseif($findType=="follow"){//看自己关注列表
  47. $redis->zInter($fofaKey,array($findKey,$fansKey));
  48. }
  49. }
  50. //互粉集合
  51. $fofaSet=$redis->zRevRange($fofaKey,0,-1);
  52. returnarray(
  53. "findSet"=>$findSet,//要查询的集合
  54. "fofaSet"=>$fofaSet,//互粉的集合
  55. "findInterFollowSet"=>$findInterFollowSet,//要查询的集合与我的关注交
  56. "findInterFansSet"=>$findInterFansSet//要查询的集的与我的粉丝交
  57. );
  58. }

以上函数已经求出了所需要的集合,然后就是关系状态判断了。

  1. /*
  2. *isSelf:是否查看自己的列表
  3. *findType:查看的是粉丝还是关注列表1:关注,2:粉丝
  4. *userInfoArr:用户详细信息数组
  5. */
  6. functiongetUserInfoList($isSelf,$findType,$userInfoArr,$findSet,$fofaSet,$interFansSet,$interFollowSet){
  7. $userInfoList=array();
  8. foreach($findSetas$userID=>$favoTime){
  9. if(!in_array($userID,array_keys($userInfoArr)))continue;
  10. $userInfo=newUserInfo($userInfoArr[$userID]);
  11. $userInfo=$userInfo->format();
  12. if(in_array($userID,$fofaSet)){
  13. $userInfo['favoFlag']=3;//互相关注
  14. }else{
  15. if($isSelf){
  16. $userInfo['favoFlag']=$findType;
  17. }else{
  18. if(in_array($userID,$interFansSet)){
  19. $userInfo['favoFlag']=2;//我的粉丝
  20. }elseif(in_array($userID,$interFollowSet)){
  21. $userInfo['favoFlag']=1;//我的关注
  22. }else{
  23. $userInfo['favoFlag']=0;//无关系
  24. }
  25. }
  26. }
  27. $userInfo['favoTime']=$favoTime;
  28. array_push($userInfoList,$userInfo);
  29. }
  30. return$userInfoList;
  31. }

©本文为清一色官方代发,观点仅代表作者本人,与清一色无关。清一色对文中陈述、观点判断保持中立,不对所包含内容的准确性、可靠性或完整性提供任何明示或暗示的保证。本文不作为投资理财建议,请读者仅作参考,并请自行承担全部责任。文中部分文字/图片/视频/音频等来源于网络,如侵犯到著作权人的权利,请与我们联系(微信/QQ:1074760229)。转载请注明出处:清一色财经

(0)
打赏 微信扫码打赏 微信扫码打赏 支付宝扫码打赏 支付宝扫码打赏
清一色的头像清一色管理团队
上一篇 2023年5月6日 09:11
下一篇 2023年5月6日 09:11

相关推荐

发表评论

登录后才能评论

联系我们

在线咨询:1643011589-QQbutton

手机:13798586780

QQ/微信:1074760229

QQ群:551893940

工作时间:工作日9:00-18:00,节假日休息

关注微信