C # use Redis to store and query data of fans and friends

Posted by knowram on Fri, 11 Feb 2022 21:43:12 +0100

Due to the development needs, add the fan attention module

 

In the relationship of friends' attention, there are mainly the above three states, namely:


My fans
My follow
mutual

The design idea is as follows:


General idea: we use zset in redis to complete the whole function. The reason is that zset has the functions of sorting (we should arrange according to the reverse order of attention time) and de duplication (we can't pay attention to the same user multiple times) For a user, we store two sets, one is to save the person who pays attention to the user, and the other is to save the person who pays attention to the user
Specific command reference: http://doc.redisfans.com/sorted_set/index.html
The commands used are:
1. Zadd add member: command format: zadd key score member [score...]
2. Zrem remove a member: command format: zrem key member [member...]
3. Zcard counts the number of members in the set: command format: zcard key
4. Zrange query members in the set: command format: zrange key start stop [with scores]
Description: returns the members of the specified interval. The member positions are sorted by increasing the score value (from small to large). The with scores option is used to return the member with its score value
5. zrevrange has the opposite effect with zrange
6. Zrank get the ranking of members: command format: zrank key member
Description: returns the ranking of members in the ordered set key. Members are arranged in ascending order of score value (from small to large). The ranking starts with 0, that is, the lowest score value is 0. Return value: returns the ranking of members. If member does not exist, return nil
7. Zinterstore takes the intersection of two sets: command format: zinterstore destination numkeys key...] [AGGREGATE SUM|MIN|MAX]
Description: calculates the intersection of a given one or more ordered sets. The number of given keys must be specified with the numkeys parameter, and the intersection (result set) is stored in the destination. By default, the score value of a member in the result set is the sum of the member's score values in all given sets.
Return value: the number of result set members saved to destination.

 

Redis implementation ideas

 

1. Add attention


There are two steps to adding attention:

Add the other party's Bid to your attention A list;

Redis::ZADD("A:follow", time(), B)

Add your own Aid to the fan list of opposite party B:

Redis::ZADD("B:fans", time(), A)

2. Cancel attention


There are also two steps to cancel attention:

Remove the other party's Bid from the following A list of his A;

Redis::ZREM("A:follow", B)

Remove your Aid from the other party's fan B list:

Redis::ZREM("B:fans", A)

3. Attention list

Redis::ZRANGE("A:follow", 0 , -1)

4. Fan list

Redis::ZRANGE("A:fans", 0 , -1)

5. Personal relationships


5.1 one way attention
A pays one-way attention to B, which should meet two conditions at the same time: 1. There is B in a's attention list (or there is a in B's fan list); 2. There is no B in a's fan list (or there is no a in B's follow list).

Redis::ZSCORE("A:fans", B) # does not return scores

Redis::ZSCORE("A:follow", B) # returns the score

5.2. Whether mutual powder
Whether a and B are fans of each other should meet two conditions at the same time: 1. There is B in a's attention list (or there is a in B's fan list); 2. A's fan list has b (or B's follow list has A). At the same time, it is mutual powder.

Redis::ZSCORE("A:fans", B) # returns the score

Redis::ZSCORE("A:follow", B) # returns the score

6. Quantity related


6.1 number of concerns
Redis::ZCARD("A:follow"); # Return quantity

6.2 number of fans
Redis::ZCARD("A:fans"); # Return quantity

7. Sort out all the people


7.1. Retrieve the user's id according to the time of interest

Redis::ZREVRANGE("A:fans", 0, -1, TRUE); # Reverse order value

7.2. Take out the user's id according to the attention time sequence

Redis::ZRANGE("A:fans", 0, -1, TRUE); # Sequential value

8. Get mutual powder list

Redis::SInter("A:follow","B:follow"); 

or

Redis::SInterStore("A_B:follow" , "A:follow","B:follow"); / / select storage

Redis:: zrange ("a_b: follow", 0, - 1) / / get again

The specific function implementation code is divided into 8 parts

public class RedisFollowHelper

  {

      //(FOLLOW_USERS)

      private static string FOLLOW_USERS = "gz:{0}:follow";

      //(FANS_USERS) fan list

      private static string FANS_USERS = "gz:{0}:fans";



      private static string INFO_USERS = "uinfo:{0}";

      private static int INFO_USERS_TIME = 86400;





      /// <summary>

      /// 0. Determine whether you have paid attention

      /// </summary>

      /// <param name="cid"></param>

      /// <param name="followId"></param>

      /// <returns></returns>

      public static bool isFollowed(long cid, long followId)

      {

          string followUsersKey = string.Format(FOLLOW_USERS, cid);

          object value = RedisHelper.ZScore(followUsersKey, followId);

          return value != null;

      }

      followId Pay attention to others,Determine whether you have paid attention

      //public static bool isFollowedByFollowId(long followId, User user)

      //{



      //    string fanUsersKey = string.Format(FANS_USERS, followId);

      //    Object value = RedisHelper.HGet(fanUsersKey, user.getId().ToString());

      //    return value != null;

      //}



      /// <summary>

      /// 1.  Add attention

      /// </summary>

      /// <param name="cid"></param>

      /// <param name="followId"></param>

      public static void follow(long cid, long followId)

      {

          long dt = CFunc.GetTimeStamp(DateTime.Now);

          //1. Add the other party's id to your attention list;

          string followUsersKey = string.Format(FOLLOW_USERS, cid);

          RedisHelper.ZAdd(followUsersKey, (dt, followId));



          //2. Add your id to the other party's fan list:

          string fanUsersKey = string.Format(FANS_USERS, followId);

          RedisHelper.ZAdd(fanUsersKey, (dt, cid));

      }

      /// <summary>

      /// 2.  Cancel attention

      /// </summary>

      /// <param name="cid"></param>

      /// <param name="followId"></param>

      public static void unFollow(long cid, long followId)

      {

          //1. Remove the other party's id from your attention list;

          string followUsersKey = string.Format(FOLLOW_USERS, cid);

          RedisHelper.ZRem(followUsersKey, followId);



          //Remove your id from the other party's fan list:

          string fanUsersKey = string.Format(FANS_USERS, followId);

          RedisHelper.ZRem(fanUsersKey, cid);

      }

      /// <summary>

      /// 3.  Follow list

      /// </summary>

      ///< param name = "userid" > viewer's user ID < / param >

      /// <param name="start"></param>

      /// <param name="stop"></param>

      /// <returns></returns>

      public static string[] Follows(long userId, long start = 0, long stop = -1)

      {

          string followsUsersKey = string.Format(FOLLOW_USERS, userId);

          string[] objectMap = RedisHelper.ZRange(followsUsersKey, start, stop);

          return objectMap;

      }

      /// <summary>

      /// 4.  Fan list

      /// </summary>

      /// <param name="followId"></param>

      /// <param name="start"></param>

      /// <param name="stop"></param>

      /// <returns></returns>

      public static string[] Fans(long userId, long start = 0, long stop = -1)

      {

          string fansUsersKey = string.Format(FANS_USERS, userId);

          string[] objectMap = RedisHelper.ZRange(fansUsersKey, start, stop);

          return objectMap;

      }



      /// <summary>

      /// 5.  Character relationship

      /// 1.cidA unidirectional attention cidB

      /// </summary>

      /// <param name="cidA"></param>

      /// <param name="cidB"></param>

      public static bool LinkAtoB(long cidA, long cidB)

      {

          string fanKey = string.Format(FANS_USERS, cidA);

          string followKey = string.Format(FOLLOW_USERS, cidA);

          //A pays one-way attention to B, which should meet two conditions at the same time: 1. There is B in a's attention list (or there is a in B's fan list); 2. There is no B in a's fan list (or there is no a in B's follow list).

          if (RedisHelper.ZScore(followKey, cidB) > 0 && RedisHelper.ZScore(fanKey, cidB) == null)

          {

              return true;

          }

          return false;

      }

      /// <summary>

      /// 2. Mutual powder or not

      /// </summary>

      /// <param name="cidA"></param>

      /// <param name="cidB"></param>

      /// <returns></returns>

      public static bool LinkAandB(long cidA, long cidB)

      {

          string fanKey = string.Format(FANS_USERS, cidA);

          string followKey = string.Format(FOLLOW_USERS, cidA);

          //Whether a and B are fans of each other should meet two conditions at the same time: 1. There is B in a's attention list (or there is a in B's fan list); 2. A's fan list has b (or B's follow list has A). At the same time, it is mutual powder.

          if (RedisHelper.ZScore(followKey, cidB) > 0 && RedisHelper.ZScore(fanKey, cidB) > 0)

          {

              return true;

          }

          return false;

      }



      /// <summary>

      ///6.1. Number of my concerns

      /// </summary>

      /// <param name="userId"></param>

      /// <returns></returns>

      public static long FollowsCount(long userId)

      {

          string followsCountKey = string.Format(FOLLOW_USERS, userId);

          long iCount = RedisHelper.ZCard(followsCountKey);

          return iCount;

      }

      /// <summary>

      ///6.2. Number of my fans

      /// </summary>

      /// <param name="userId"></param>

      /// <returns></returns>

      public static long FansCount(long userId)

      {

          string fansCountKey = string.Format(FANS_USERS, userId);

          long iCount = RedisHelper.ZCard(fansCountKey);

          return iCount;

      }



      /// <summary>

      ///7.1 retrieve the user's id according to the time flashback added by the fans

      /// </summary>

      /// <param name="cid"></param>

      /// <param name="start"></param>

      /// <param name="stop"></param>

      /// <returns></returns>

      public static string[] FansByTimeDesc(long cid, long start = 0, long stop = -1)

      {

          string fansCountKey = string.Format(FANS_USERS, cid);

          string[] objectMap = RedisHelper.ZRevRange(fansCountKey, start, stop);

          return objectMap;

      }



      /// <summary>

      /// 8. Get a list of common concerns

      /// </summary>

      /// <param name="cidA"></param>

      /// <param name="cidB"></param>

      /// <param name="start"></param>

      /// <param name="stop"></param>

      /// <returns></returns>

      public static string[] Mutuals(long cidA, long cidB, long start = 0, long stop = -1)

      {

          string followsUsersA = string.Format(FOLLOW_USERS, cidA);

          string followsUsersB = string.Format(FOLLOW_USERS, cidB);

          string[] objectMap = RedisHelper.SInter(followsUsersA, followsUsersB);

          //You can also use redishelper Sinterstore, store and query

          if (stop > start)

          {

              long iCount = objectMap.Length;

              if (start <= iCount)

              {

                  if (stop > iCount)

                  {

                      stop = iCount;

                  }

                  int j = 0;

                  string[] newMap = new string[] { };

                  for (long i = start; i < stop; i++)

                  {

                      newMap[j] = objectMap[i];

                      j++;

                  }

                  return newMap;

              }

          }

          return objectMap;

      }



      /// <summary>

      ///7.2 retrieve the user's id according to the time of interest

      /// </summary>

      /// <param name="cid"></param>

      /// <param name="start"></param>

      /// <param name="stop"></param>

      /// <returns></returns>

      public static string[] FollowByTimeAsc(long cid, long start = 0, long stop = -1)

      {

          string fansCountKey = string.Format(FOLLOW_USERS, cid);

          string[] objectMap = RedisHelper.ZRevRange(fansCountKey, start, stop);

          return objectMap;

      }





      public static JObject getUserInfo(long cid, bool Refresh = false)

      {

          string UsersKey = string.Format(INFO_USERS, cid);

          string userstr = "";

          if (Refresh == false)

          {//Force refresh data

              userstr = RedisHelper.Get(UsersKey);

          }

          JObject jo = new JObject();

          if (string.IsNullOrEmpty(userstr))

          {

              

              //Query database data

              DataSet ds = ;



              if (ds.Tables[0].Rows.Count > 0)

              {

                  jo.Add("cid", cid);

                  jo.Add("nickname", CFunc.SafeToStr(ds.Tables[0].Rows[0]["nickname"]));

                  jo.Add("headpic", 1);// CFunc.ObjToInt32(ds.Tables[0].Rows[0]["regtime"]);

                  jo.Add("xkpic", 1);// CFunc.ObjToInt32(ds.Tables[0].Rows[0]["logindate"]);





                  RedisHelper.Set(UsersKey, jo, INFO_USERS_TIME);



              }

              ds.Clear();

          }

          else

          {

              jo = (JObject)JsonConvert.DeserializeObject(userstr);

              RedisHelper.Expire(UsersKey, INFO_USERS_TIME);

          }

          return jo;

      }

      internal static bool infoChanged(long cid)

      {

          string UsersKey = string.Format(INFO_USERS, cid);

          if (RedisHelper.Exists(UsersKey))

          {

              RedisHelper.Del(UsersKey);

              return true;

          }

          return false;

      }

  }

 

 

Topics: C# Redis