【问题标题】:Search users and sort by most number of mutual friends in Redis?在 Redis 中搜索用户并按最多的共同好友排序?
【发布时间】:2016-11-18 15:33:33
【问题描述】:

我有一个包含 500 万用户的潜在数据库,其中每个用户都有一定数量的朋友。我需要做的是实现搜索,以便用户可以按某些属性(即其他用户的性别等)进行过滤,这部分相当简单。

用户 A 搜索所有男性并获取结果集。用户 B、用户 C、用户 D

但是,用户还应该可以选择按用户 A 与结果集中所有用户的共同好友数量对搜索结果进行排序

假设
用户 A 和用户 B = 3 个共同好友
用户 A AND 用户 C = 8 个共同好友
用户 A AND 用户 D = 5 个共同好友

然后,搜索应该按以下顺序对结果进行排序

用户 C、用户 D、用户 A

最重要的是,由于结果将显示在网页上,因此我还需要支持分页,以便每次用户在搜索结果之间导航时不会处理所有 500 万左右的条目。

Web 代码是用 C# 编写的,但就数据库而言,我非常开放,可以使用 SQL、NoSQL 或 Redis。主要优先事项是高性能,因此 Redis 似乎是一个不错的选择。如何从数据存储和伪代码的角度实现这样的搜索需求?

【问题讨论】:

    标签: c# sql .net sql-server redis


    【解决方案1】:

    在 redis 中,您可能希望将其存储在 zset 中;没有内置的红色自动索引,所以当你添加或删除朋友时,你需要zaddzincrbyzincrby 减去一个负数)。然后你只需zrangezrangebyscore 来查询它。这些方法都可以在 NuGet 上的 StackExchange.Redis 包中的 SortedSet 前缀下使用。

    【讨论】:

    • “将其存储在 zset 中”是指存储每个用户个人资料还是共同的朋友?如果是共同的朋友,那么这不会创建 N x N 个集合,500 万将是 5 万亿个集合。您能否详细说明您的方法?
    【解决方案2】:

    我的两分钱。

    如果您将性别索引保持为一个集合,您可以利用 ZINTERSTORE,并且每个用户的共同朋友计为一个 SortedSet(分数是共同朋友计数)。 此外,每个用户还需要一组朋友。

    对于性别,请使用具有密钥格式的 Set:gender:{gender},每个项目都是一个用户 ID。

    对于朋友,请使用带有密钥格式的 Set:friends:{userId},每个项目都是一个用户 ID。

    对于共同的朋友,使用密钥格式为:mutual:{userId} 的 SortedSet,每个项目将是一个用户 ID,分数将是共同朋友的数量。

    所以,当你添加一个用户时:

    void AddUser(string user, string gender)
    {
        // Add to a gender set  "gender:{gender}"->{users}
        db.SetAdd($"gender:{gender}", user);
    }
    

    添加两个用户之间的友谊:

    void AddFriendship(string user1, string user2)
    {
        // All friends of user1, should increment its mutual count with user2
        var user1Friends = db.SetMembers($"friends:{user1}");
        foreach(var user1Friend in user1Friends)
        {
            db.SortedSetIncrement($"mutual:{user1Friend}", user2, 1);
            db.SortedSetIncrement($"mutual:{user2}", user1Friend, 1);
        }
    
        // All friends of user2, should increment its mutual count with user1
        var user2Friends = db.SetMembers($"friends:{user2}");
        foreach (var user2Friend in user2Friends)
        {
            db.SortedSetIncrement($"mutual:{user2Friend}", user1, 1);
            db.SortedSetIncrement($"mutual:{user1}", user2Friend, 1);
        }
    
        // Add to friend sets   "friends:{user}->{users}"
        db.SetAdd($"friends:{user1}", user2);
        db.SetAdd($"friends:{user2}", user1);
    }
    

    并按共同好友数量排序的性别获取用户:

    static IEnumerable<string> GetUsersByGenderOrderByMutualFriends(string user, string gender)
    {
        var db = mux.GetDatabase();
        var tempKey = "temp";
        db.SortedSetCombineAndStore(SetOperation.Intersect, tempKey, $"gender:{gender}", $"mutual:{user}", Aggregate.Sum);
        var result = db.SortedSetRangeByRank(tempKey, 0, -1, Order.Descending).Select(x => x.ToString());
        db.KeyDelete(tempKey);
        return result;
    }
    

    【讨论】:

      猜你喜欢
      • 2012-05-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-06-20
      • 1970-01-01
      • 1970-01-01
      • 2011-04-12
      • 1970-01-01
      相关资源
      最近更新 更多