当前位置: 首页 > 科技观察

如何使用Redis实现follow关系生成的四种关系状态

时间:2023-03-14 08:09:16 科技观察

微博follow关系:FollowFollowers双向follow(mutualfollower)非关系需求分析在微博中,每个用户都有一个followlist和一个fan列表。用户可以查看自己的关注和粉丝列表,也可以查看其他人的关注和粉丝列表。此外,还需要显示列表中每个人和当前查看者的关注状态。状态的可能性就是上面提到的四种关系状态。问题可以分两种情况来看:看自己的follow,followerlist,看别人的follow,followerlist看自己的follow,followerlist:这种情况比较简单。比如你看你的观察名单,名单上的人和你的关系状态不能是“无关系”或者“粉丝”。只有可能的“关注”和“双向关注”。同样,粉丝列表也只有两种状态。看别人的关注度,粉丝榜:这是最复杂的情??况。如果你看别人的关注列表,列表里的人可能和你自己有以上四种关系状态。从集合的图表分析如上图所示。左边的圆圈代表用户的关注列表,右边的圆圈代表粉丝列表,下面的圆圈代表要查看的列表(合集)。用follow、fans、find分别表示这三组。在查看自己的列表时,实际上意味着find集合是上述集合之一的子集。比如查你的fans,就说明find是fans的一个子集,查你的followers,就说明find是follow的子集。在查看别人的列表时,此时图形中产生了三个集合的交集。要查询的收藏中的用户可能是你的粉丝,关注收藏,也可能不是。也就是说,它可以是任何一种关系状态。问题的根源在于我们需要计算每个用户与当前用户的关系状态。要解决这四种关系状态,我们必须求出图中下部的三个小交点。待查询集合与我的粉丝的交集待查询集合与我的粉丝的交集待查询集合与我的粉丝的交集不在这三个小交集中的用户是无关系状态的用户。假设我们使用如下一组命名:follow集合follow:userID粉丝集合fans:userIDinter-follow集合(临时)fofa:待查询userID集合(临时)find:userID待查询集合与我的follow交集(临时)find_inter_follow:userID待查询集合与我的粉丝的交集(临时)find_inter_fans:userID待查询集合与我的粉丝的交集(临时)find_inter_fofa:userIDfind中的其他人未被关注使用SortedSet存储关系分数来存储注意力一次,每个用户存储两个集合。follow:userID存储用户的关注度,fans:userID存储用户的粉丝。所以我们可以设计一个函数来找到这些状态的集合。函数返回:"findSet"=>$findSet,//要查询的集合"fofaSet"=>$fofaSet,//相互关注的集合"findInterFollowSet"=>$findInterFollowSet,//要查询的集合相交withmyfollowers"findInterFansSet"=>$findInterFansSet//要查询的集合与我的粉丝相交,找出以上四组,然后判断关系状态,先判断是不是互粉,如果不是,再判断是不是我的follower是,如果不是,再判断是不是我的fan。如果不是,没关系。这样就可以获得状态。/**userID:当前用户id*targetUserID:被查看者id*findType:正在查看哪个列表*findStart:分页查看列表的起始位置*findEnd:被查看列表的结束位置paging*/functiongetChunkSets($redis,$userID,$targetUserID,$findType,$findStart,$findEnd){$fansKey="fans:".$userID;$followKey="follow:".$userID;$findKey="查找:".$userID;$targetKey=$findType.":".$targetUserID;$fofaKey="find_inter_fofa:".$userID;$findInterFollowKey="find_inter_follow:".$userID;$findInterFansKey="find_inter_fans:".$userID;//find获取要查询的集合元素$findSet=$redis->zRevRange($targetKey,$findStart,$findEnd,TRUE);//要查询的集合与我的注意力相交$findInterFollowSet=array();//要查询的集合集合和我的粉丝$findInterFansSet=array();//先清空临时集合$redis->del($findKey);$redis->del($fofaKey);$redis->del($findInterFollowKey);$redis->del($findInterFansKey);//保存foreach($findSetas$uid=>$score){$redis->zAdd($findKey,$score,$uid);}//查找共同粉丝集合if($userID!=$targetUserID){//看看其他的$redis->zInter($fofaKey,array($findKey,$fansKey,$followKey));/**如果不是看自己的列表,还需要*1:要查询的集合与我的关注者相交*2:要查询的集合与我的粉丝相交*/$redis->zInter($findInterFollowKey,array($findKey,$followKey));$redis->zInter($findInterFansKey,array($findKey,$fansKey));$findInterFollowSet=$redis->zRevRange($findInterFollowKey,0,-1);$findInterFansSet=$redis->zRevRange($findInterFansKey,0,-1);}else{if($findType=="fans"){//粉丝列表自己看$redis->zInter($fofaKey,array($findKey,$followKey));}elseif($findType=="follow"){//查看你的关注列表$redis->zInter($fofaKey,array($findKey,$fansKey));}}//互相关注Collection$fofaSet=$redis->zRevRange($fofaKey,0,-1);returnarray("findSet"=>$findSet,//要查询的collection"fofaSet"=>$fofaSet,//共同粉丝的集合"findInterFollowSet"=>$findInterFollowSet,//要查询的集合与我的粉丝相交"findInterFansSet"=>$findInterFansSet//要查询的集合与我的粉丝相交);}以上函数已经得到了需要的集合,然后判断关系状态/**isSelf:是否查看自己的列表*findType:是否查看粉丝或关注列表1:关注,2:粉丝*userInfoArr:用户详情数组*/functiongetUserInfoList($isSelf,$findType,$userInfoArr,$findSet,$fofaSet,$interFansSet,$interFollowSet){$userInfoList=array();foreach($findSetas$userID=>$favoTime){if(!in_array($userID,array_keys($userInfoArr)))继续;$userInfo=newUserInfo($userInfoArr[$userID]);$userInfo=$userInfo->format();if(in_array($userID,$fofaSet)){$userInfo['favoFlag']=3;//互相跟随}else{if($isSelf){$userInfo['favoFlag']=$findType;}else{if(in_array($userID,$interFansSet)){$userInfo['favoFlag']=2;//我的粉丝}elseif(in_array($userID,$interFollowSet)){$userInfo['favoFlag']=1;//我的关注}else{$userInfo['favoFlag']=0;//没有关系}}}$userInfo['favoTime']=$favoTime;array_push($userInfoList,$userInfo);}return$userInfoList;}