首页 > 解决方案 > Swift/Firestore 在排名系统中查询集合

问题描述

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

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

假设我在 Firestore 集合中有 1,000 个用户,每个用户都有一个相关的分数。用户也可以互相关注。假设“用户 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 个用户的同时保持全球排行榜中的排名?我需要采取不同的方法来完成这样的任务吗?

标签: swiftdatabasefirebasegoogle-cloud-firestorenosql

解决方案


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

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 设为 Array 而不是集合,您不必在可能数百个地方维护相同的 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. 同时,我会增加被关注用户的“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');

推荐阅读