【问题标题】:Swift/Firestore Query a Collection in a Ranking SystemSwift/Firestore 在排名系统中查询集合
【发布时间】:2021-02-05 19:40:21
【问题描述】:

我越来越感激我从 SO 社区学到了很多东西,所以提前感谢您抽出宝贵的时间。

以下是我需要完成的工作的摘要:

假设我在 Firestore 集合中有 1000 个用户,每个用户都有一个相关的分数。用户也可以互相关注。假设“用户 A”需要对他/她关注的 100 个用户运行查询,同时保持每个用户在全球 1000 个用户中的排名。 IE。用户 A 关注排名第 1 人、排名第 237 人、排名第 999 人等。

我的数据目前的结构如下所示:

user_information (Collection)
-- user_id (Document)
---- user_score (Int Field) <- the field in which the query is sorted by
users (Collectiion)
-- user_id (Document)
---- following_users (Collection) <- Running the query on these users
------ user_id (Document)

following_users 的相对于彼此的分数对它们进行排序很容易,但是我如何在仅查询被关注的 100 个用户的同时保持全球排行榜中的排名?我需要采取不同的方法来完成这样的任务吗?

【问题讨论】:

    标签: swift database firebase google-cloud-firestore nosql


    【解决方案1】:

    在回答您的最后一个问题之前,让我分享一下:我的方法是通过以下方式调整您的数据库结构:

    user_information (Collection)
    -- user_id (Document)
    ---- user_score (Int Field) <- the field in which the query is sorted by
    users (Collectiion)
    -- user_id (Document)
    ---- following_users (Array Field) [Array field of user_id's this user is following]
    

    通过将 following_users 设为数组而不是集合,您不必在可能数百个地方维护相同的 user_id 文档。

    假设用户 A、R、D、S、T、(...) 都关注用户 H,这意味着您的用户 H 的文档应该在任何地方都相同。您必须使用事务来确保用户排名在任何地方都相同,无论何时发生变化。这对于您添加到 user_id 文档的任何新字段都可能相同。

    将其扩展到仅 10,000 个用户,您的写入操作数量可能是您实际需要的 100 倍。

    通过只引用一个数组中的关注用户,过程是这样的:

    1. 查询当前用户文档
    2. (可选):为“显示我关注的用户”提供一个 UI 按钮
    3. 请求该数组中的文档,并可能按排名排序。

    如果您想跳过第 2 步,那么您可以直接查询关注的用户,按排名排序,例如限制为 10 个结果。然后滚动以加载更多或单击下一步。 (搜索“分页的 Firestore 查询”或“Firestore 查询游标”)。

    现在,回答您的问题“但是如何在仅查询被关注的 100 个用户的同时保持全球排行榜中的排名?”...

    在这种情况下,我会这样做:

    在您的 user_id 文档中引入一个新字段,称为:'followerCount',将其设为 Integer。

    1. 每次用户决定关注另一个用户时,我都会将关注添加到关注者的“following_users”数组字段中。
    2. 同时,我会increment被关注用户的“followerCount”。
    3. 如果关注者决定取消关注,我会从“following_users”数组中删除关注的 user_id,并减少关注用户的“followerCount”。

    旁注,我会使用“Firestore Transactions”(google it)进行此类操作,以确保它们同时发生。

    附注 #2:在 Firestore 中,您可以递增 -1 来递减。

    旁注 #3:在 following_users 数组字段中,我鼓励您使用 FieldValue.arrayUnion 添加 user_id's 和 FieldValue.arrayRemove 以删除它们。

    以这种方式构建事物,在排行榜上执行查询将非常容易。示例:

    await leaderboard_query = db.collection(user_information).where('followerCount', '>', 0).orderBy('user_score');
    

    【讨论】:

      猜你喜欢
      • 2020-01-14
      • 2019-07-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-09-21
      • 2020-10-10
      相关资源
      最近更新 更多