【问题标题】:Fetching array equal to any array element ordered by field - Swift - Firestore获取等于按字段排序的任何数组元素的数组 - Swift - Firestore
【发布时间】:2021-12-09 00:37:33
【问题描述】:

我需要在一个集合中进行 Firestore 查询:

  1. 按字段“时间戳”排序
  2. “uid”字段等于字符串数组的任何元素(超过 10 个)
  3. 我需要对查询进行分页,以便以后能够从精确的时间戳开始执行更多查询

代码应如下所示:

Firestore.firestore()
    .where(field: "uid", in: arrayOfUids)
    .order(by: "timestamp", descending: false)
    .limit(to: 5)

或者在从特定时间戳开始的情况下

Firestore.firestore()
    .where(field: "uid", in: arrayOfUids)
    .startAt("timestmap", lastTimestampFetched)
    .order(by: "timestamp", descending: false)
    .limit(to: 5)

我怎样才能达到这个结果? 在这个topic 中,建议在每次调用中执行多个调用过滤,数组中最多包含 10 个元素(Firestore 能够比较的最大数组元素数),但我没有按时间戳排序的约束.

编辑: 我无法在客户端订购查询结果,这对我的用例没有帮助。 假设我们有 30 个 uid 要查询: 首先,我们必须将这些 uid 分成 10 个一组。

所以我们将有 3 组,每组 10 个 uid(使用 Firestore 查询的最大数组长度);对于每个组,我们将执行一个单独的查询,如下所示:

Firestore.firestore()
        .where(field: "uid", in: arrayOfTenUids)
        .startAt("timestmap", lastTimestampFetched)
        .order(by: "timestamp", descending: false)
        .limit(to: 5)

对于每个查询,我们保存最后一个文档时间戳,以便能够通过分页执行连续查询。

问题来了,我们将有多个最后一个时间戳,因为我们正在执行多个查询,我们要保存哪个时间戳?

第一个选项:所有最后一个时间戳的最后一个时间戳

第二个选项:所有最后一个时间戳中的第一个时间戳

第一种情况 -> 在连续查询中,我们将获取一些先前已获取的文档

第 2 种情况 -> 在连续查询中,我们会遗漏一些之前获取的文档(因为一个查询的最后一个时间戳可能在另一个查询的最后一个时间戳之后)

这个话题真的很难解释,但我已经尽力了。

【问题讨论】:

  • 这个问题和预期的结果有点不清楚。问题中的代码将返回所有具有与 arrayOfUid 之一匹配的 uid 字段值的文档。该代码不起作用吗?还是要查询数组中超过 10 个值?
  • 正好是第二个选项,我要查询数组中超过10个值
  • @alexmamo 在您提供的链接中的答案是正确的。所述数据的排序将没有影响。实际上,考虑到这一点,您将需要执行多个查询并将它们组合到代码中,以便应用排序 - 一旦您拥有所有数据。还有其他的吗?
  • 我想使用时间戳对文档进行排序,因为集合中的文档很多,我需要对查询进行分页,这就是为什么我想对数据进行排序以便我可以获取其中一些而不是所有集合,但仍然订购。
  • topic中的答案建议在客户端合并查询的结果。你试过在那里排序吗?

标签: ios swift firebase google-cloud-firestore


【解决方案1】:

基于 cmets,让我尝试创建当前的 Firestore 结构并重新陈述目标,然后提出解决方案。我暂时忽略了时间戳:

Posts (collection)
   post_0
      uid: uid_4
   post_1:
      uid: uid_1
   post_2:
      uid: uid_3
   post_3:
      uid: uid_2

然后

Matches (collection)
   uid_0
      uid_1
      uid_2
      uid_3
   uid_5
      uid_4

目标是让当前用户,比如 uid_0,读取他们在 Matches 集合中的节点,这将是这个

   uid_0
      uid_1
      uid_2
      uid_3

然后从 uid 字段与该列表中的 uid 匹配的 Post 节点获取帖子。结果应该是 post_1、post_2 和 post_3。

问题是用户节点 uid_0 可能有几十个子 uid,因为 Firestore 使用“in”函数一次最多只能匹配 10 个

.where(field: "uid", in: arrayOfUids)

这需要多次读取 - 然后是时间戳和排序以及分页问题。

我的建议是简化;如果上述目标是正确的,而不是在每个帖子中存储那些不同的 uid,只需存储当前用户的 uid,就像这样

Posts (collection)
   post_0
      uid: uid_2
   post_1:
      uid: uid_0
   post_2:
      uid: uid_0
   post_3:
      uid: uid_0

然后在 Posts 节点中查询 uid = uid_0。结果将完全相同,并且实现和维护更简单,然后时间戳/分页问题不再是问题。

显然这是一个简单的例子;我想您想在每个帖子中存储多个 uid,因此无论哪个用户登录都可以检索他们选择的帖子。为此,请使用array contains 检索与该用户匹配的帖子。

Posts (collection)
   post_0
      uid_array: 
         uid_2
         uid_9
         uid_21

【讨论】:

  • 您完全理解我的意思,非常感谢您的回答。基本上,每当创建新匹配时,我需要在“uid_array”中添加一个新的 uid 到与匹配的 uids 对应的每个 Post 。显然,我会在服务器端做,你认为这是正确的方法吗?
  • @StackGU 听起来你走上了正轨。
猜你喜欢
  • 1970-01-01
  • 2022-01-20
  • 1970-01-01
  • 1970-01-01
  • 2014-12-19
  • 2019-02-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多