Redisで微博の注目関係を実現します。

5859 ワード

関係に関心を持つ4つの関係状態
  • 関心
  • ファン
  • 双方向フォロー
  • 大丈夫です。
    需要分析
    マイクロブログでは、各ユーザーに注目リストがあり、ファンリストがあります。ユーザーは自分の関心を見ることができて、ファンリスト、他の人の関心をも見ることができて、ファンリスト。そして、リスト内の一人一人と現在の閲覧者の注目状態を表示します。状態の可能性は上に述べた四つの関係状態です。
    問題は二つの状況に分けて見られます。
    1、自分の注目を見る、ファンリスト
    2、他の人の注目を見て、ファンリスト
    自分の注目を見ると、ファンリスト:
    この場合は比較的簡単です。例えば自分の注目リストを見ると、リストの中の人と自分の関係状態は「大丈夫」と「ファン」ではありません。「関心」と「双方向関心」だけかもしれません。同様に、ファンリストも2つの状態しかない。
    他の人の注目を見ると、ファンリスト:
    これは一番複雑な状況です。リストを見れば、リストの中の人と自分は上記の四つの関係状態があるかもしれません。
    集合の図から分析する

    上の図に示すように。左の円はユーザーの注目リストを表し、右の円はファンリストを表し、下の円は表示するリスト(集合)を表します。それぞれフォロー、ファン、findでこの3つの集合を表明します。
    自分のリストを見ると、フィールドのセットは上のセットのいずれかのサブセットであることを表します。例えば、自分のファンを見ると、findはファンのサブセットであり、自分の関心を見て、findはフォローのサブセットであるということです。
    他の人のリストを見ると、図中に3つのセットが交差します。集合中のユーザを調べるには、あなたのファンの中にいるかもしれません。集合中に注目しても、いないかもしれません。つまり、任意の関係状態かもしれません。問題の根本は、各ユーザと現在のユーザとの関係状態を計算します。四つの関係状態を解くことを要求します。私たちは必ず図の中の下の部分の三つの小さい交差点を要求します。
  • 検索するセットと私のインターフェース
  • のクエリのセットと私の関心のクロス
  • が調べたいセットは私のファンと一緒に
  • です。
    この三つの小さな交差点にいないユーザーは無関係状態のユーザです。
    もし私たちが次のような名前を付けたら、
    注目の集まり
    フォロワー:userIDファン集合ファン:userID
    相互集合(仮)
    fofa:userIDが検索するセット(仮)find:userID
    検索する集合は私の関心と結びついています。(臨時)
    find_インテル.follow:userIDが検索する集の私のファンと交錯(仮)find_インテル.ファン:userID
    検索する集合は私の相互の粉と交差します。(臨時)
    find_インテル.fofa:userID
    findの中で他は注目されていません。
    Sorted Setを使って関係を保存します。
    scoreは、関心のある時間を記憶するために使用され、各ユーザは2つのセットを記憶する。フォロワー:userIDはユーザーの注目を集め、ファン:userIDはユーザーのファンを記憶する。そこで,これらの状態の集合を求める関数を設計することができた。
    関数の戻り値:
    
    "findSet" => $findSet, //       
    "fofaSet" => $fofaSet, //      
    "findInterFollowSet" => $findInterFollowSet, //             
    "findInterFansSet" => $findInterFansSet //             
    
    以上の4つの集合を求めるなら、関係状態を判断して、相互粉かどうか判断します。相互粉ではないなら、私が注目しているかどうかを判断します。そうでなければ、私のファンかどうかを判断します。全部でないなら大丈夫です。このように状態を求めることができます。
    
    /* 
    * userID:    id 
    * targetUserID:       id 
    * findType:          
    * findStart:              
    * findEnd:              
    */ 
    function getChunkSets($redis, $userID, $targetUserID, $findType, $findStart, $findEnd) { 
     
     $fansKey = "fans:" . $userID; 
     $followKey = "follow:" . $userID; 
     $findKey = "find:" . $userID; 
     
     $targetKey = $findType. ":" . $targetUserID; 
     $fofaKey = "find_inter_fofa:" . $userID; 
     
     $findInterFollowKey = "find_inter_follow:" . $userID; 
     $findInterFansKey = "find_inter_fans:" . $userID; 
     
     //           
     $findSet = $redis->zRevRange($targetKey, $findStart, $findEnd, TRUE); 
     
     //             
     $findInterFollowSet = array(); 
     
     //             
     $findInterFansSet = array(); 
     
     //        
     $redis->del($findKey); 
     
     $redis->del($fofaKey); 
     $redis->del($findInterFollowKey); 
     $redis->del($findInterFansKey); 
     
     
     //    
     foreach ($findSet as $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)); 
      } else if ($findType == "follow") { //        
      $redis->zInter($fofaKey, array($findKey, $fansKey)); 
      } 
     } 
     
     //     
     $fofaSet = $redis->zRevRange($fofaKey, 0, -1); 
     
     return array( 
      "findSet" => $findSet, //       
      "fofaSet" => $fofaSet, //      
      "findInterFollowSet" => $findInterFollowSet, //             
      "findInterFansSet" => $findInterFansSet //             
     ); 
     } 
    
    以上の関数は必要なセットを求めました。そして関係状態の判断です。
    
    /* 
    * isSelf:           
    * findType:              1:   , 2:    
    * userInfoArr:          
    */ 
    function getUserInfoList($isSelf, $findType, $userInfoArr, $findSet, $fofaSet, $interFansSet, $interFollowSet) { 
     
     $userInfoList = array(); 
     
     foreach($findSet as $userID => $favoTime) { 
      if(!in_array($userID, array_keys($userInfoArr))) continue; 
     
      $userInfo = new UserInfo($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; //     
       } else if(in_array($userID, $interFollowSet)) { 
       $userInfo['favoFlag'] = 1; //     
       } else{ 
       $userInfo['favoFlag'] = 0; //    
       } 
      } 
       
      } 
     
      $userInfo['favoTime'] = $favoTime; 
      array_push($userInfoList, $userInfo); 
     } 
     
     return $userInfoList; 
     } 
    
    どうやってRedisを使って微博の関心関係を実現するかを紹介します。