【问题标题】:How to query Firestore collection for documents with field whose value is contained in a list如何查询具有字段值包含在列表中的文档的 Firestore 集合
【发布时间】:2019-06-10 02:13:57
【问题描述】:

我有两个 Firestore 集合,UsersPosts。以下是每个典型文档所包含内容的简化示例。

*请注意,friends 子集合中的文档 ID 等于相应用户文档的文档 ID。或者,我还可以将uid 字段添加到friends 文档和/或Users 文档。此外,还有一个与此问题无关的原因,我们将 friends 作为每个用户的子集合,但如果需要,我们将其更改为统一的根级 Friends 集合。

这种设置使得查询任何给定用户按时间顺序排序的帖子变得非常容易,只需查找owner 字段等于该用户的文档引用的Posts 文档。

尽管我们正在为 iOS、Android、 web 构建此应用程序,但我在 iOS/Swift 中通过以下方式实现了这一点。

guard let uid = Auth.auth().currentUser?.uid else {
    print("No UID")
    return
}
let firestoreUserRef = firestore.collection("Users").document(uid)
firestorePostsQuery = firestore.collection("Posts").whereField("owner", isEqualTo: firestoreUserRef).order(by: "timestamp", descending: true).limit(to: 25)

我的问题是如何查询在用户的friends 子集合中包含owner 值的Posts 文档,按时间顺序排序。换句话说,如何获取属于用户朋友的帖子,按时间排序。

以现实世界为例,考虑 Twitter,其中给定用户的提要由所有具有所有者属性的推文填充,该所有者属性的值包含在用户的以下列表中,按时间顺序排序。

现在,我从the documentation 知道 Firestore 不支持逻辑 OR 查询,所以我不能将所有朋友链接在一起。即使我可以,但对于只有少数朋友的人来说,这似乎并不是一个最佳方法。

我能想到的唯一选择是为每个朋友创建一个单独的查询。然而,这有几个问题。第一个挑战是(以平滑的方式)呈现来自许多异步获取的结果。第二个是每次更新一个查询快照(即实时更新)时,如果不重新在客户端手动重新排序集合,我就无法将数据按时间顺序合并。

是否可以构建我所描述的查询,或者我将不得不采用这种不太理想的方法?这似乎是一个相当常见的查询用例,所以如果没有办法做到这一点,我会感到惊讶。

【问题讨论】:

  • 您不能在单个查询中执行此操作。正如您已经发现的那样,您将不得不在某个地方进行迭代并进行多次查询以收集您需要的所有内容。
  • @DougStevenson 我担心可能是这种情况。任何拥有多个朋友的用户真的会很倒霉。我认为我根本无法走这条路,因为我必须一遍又一遍地进行大量的查询、排序和重新排序。我没有办法重组我的数据以使其更可行,是吗?
  • 执行多个查询并不是真正的问题。最大的问题是您阅读的文件数量。这是限制因素。只要您阅读的文档不超过实际需要,就可以了。
  • @DougStevenson 即使有大量查询不是问题,它仍然会产生您提到的有关阅读文档数量的问题。如果我有 200 个查询,每个朋友一个,那么我需要阅读至少 200 个文档——实际上比这要多得多,以确保我能够按时间顺序显示。现在,当我只尝试显示最近的 10 个文档时,我正在获取数千个文档。这不是很有效。
  • 如果您需要限制读取的文档数量,只能通过对 Firestore 中单个集合的单个查询来完成。 Firestore 并不是每项工作的最佳解决方案,因此请对可能满足您查询需求的其他替代方案持开放态度。

标签: firebase google-cloud-firestore


【解决方案1】:

如果您使用的是 Unix 时间戳,则按时间顺序排序很容易,例如1547608677790 使用 .orderBy 方法。但是,这会给您留下大量需要迭代的查询(每个朋友一个)。

所以,我认为您想重新考虑数据存储架构。

利用Cloud Functions for Firebase Triggers。当写一篇新文章时,有一个云函数计算谁应该看到它。每个用户都可以拥有一个数组类型的属性,其中包含所有unread-postsread-posts 等。

这样的事情会很快而且最省力。

【讨论】:

  • 这是有道理的,但我认为我不能使用数组类型的属性,因为 Firestore 施加了文档大小限制。但是,我想我可以将相同的概念部署为每个 Post 文档的子集合,其中子集合中的每个文档对应于应该能够看到帖子的用户。
  • document 的最大大小与field value 相同,即如果数组太小,则文档也是如此。见Maximum size for a document。注意 500 页文本等于 1 兆字节(字段大小限制)或 1,000,000 个字符。
  • 我不确定我是否在关注您的评论。如果用户应该看到的帖子数量可能不受限制,那么数组就不是一个好的解决方案。它可以放入子集合中。
猜你喜欢
  • 2021-06-10
  • 2020-06-14
  • 2021-09-10
  • 2018-05-09
  • 2021-05-05
  • 2020-05-08
  • 1970-01-01
  • 2021-05-30
  • 2018-12-07
相关资源
最近更新 更多