【问题标题】:Use an array of values to query Firestore and setup a snapshot listener使用值数组查询 Firestore 并设置快照侦听器
【发布时间】:2021-08-04 19:12:39
【问题描述】:

这是我的问题:

我有一个包含许多文档的 Firestore 集合。每小时大约有 500 个文档生成/更新并保存到集合中。

我想查询集合并为客户端提供的文档 ID 子集设置实时快照侦听器。

我想也许我可以做这样的事情(这种语法可能不正确......只是想感受一下它是否可能......但“in”不限于10个数组项目?):

const subbedDocs = ["doc1","doc2","doc3","doc4","doc5"]
docsRef.where('docID', 'in', subbedDocs).onSnapshot((doc) => {
   handleSnapshot(doc);
   });

很抱歉,该代码可能没有意义......我仍在努力学习 Firestore 的所有细节。

基本上,我要做的是获取一组 ID 并为这些 ID 设置一个 .onSnapshot 侦听器。此 ID 列表可能超过 40-50 个项目。这甚至可能吗?我试图避免只在整个集合上设置一个侦听器并过滤掉我没有“订阅”的东西,因为从资源的角度来看这似乎很浪费。

【问题讨论】:

  • 可以添加一些关于文档的细节以及其中的内容吗? (这就是让我无法编写自己的答案的原因)。客户端提供 docID 是一个奇怪的前提。我认为您应该将文档 ID 视为后端的内部。

标签: node.js firebase google-cloud-firestore


【解决方案1】:

如果您的数组中有文档 ID(看起来好像有),您可以遍历它们并在此期间启动一个侦听器:

const subbedDocs = ["doc1", "doc2", "doc3", "doc4", "doc5"];

for (let i = 0; i < subbedDocs.length; i++) {
  const docID = subbedDocs[i];

  docsRef.doc(docID).onSnapshot((doc) => {
    handleSnapshot(doc);
  });
}

最好同时收听查询和所有过滤的文档。但是如果你想用一个明确的监听器来监听它们中的每一个,那就可以了。

【讨论】:

  • 您如何建议我“同时收听查询和所有过滤的文档”。我想最终这就是我想要做的。我将如何在 Firestore 中仅查询数组中的文档 ID,然后为其附加一个侦听器?
  • @pilotGuy,所有这些监听器都可以调用handleDoc(doc),它可以将它们聚合到一个数组中,我认为你正在寻找的效果。请参阅我对另一个答案的评论。为什么是那些文档?如果您可以在查询中阐明这一点(而不是查询他们的文档 ID),那么只需查询并收听 querySnapshot。
  • 我没有建议更改数据库结构,因为我不知道您想做什么以及为什么。但是,答案中解释的理想解决方案将是一个数据库结构,您可以在其中查询您想要收听的那些文档,然后只收听您想要收听的文档中的“过滤”列表。 in 这是不可能的,因为 10 的限制以及您需要过滤到 40-50 个元素。
【解决方案2】:

如您所见,Firestore 的 in 运算符最多只允许数组中的 10 个条目。我还猜测您已将 docID 作为字段添加到文档中,因为我不相信 'docID 引用了实际的 documentid。

我会采用这种方法,因为有 10 个条目的限制。我做的是,当客户选择要遵循的文档时,将一个字段(每个文档中相同)设置为 客户的唯一 ID,这样您的查询就完全避免了限制。您可以允许无限数量的客户端侦听器(直到 Firestore 的实施限制)如果您将该客户端 ID 添加到 数组(称为“ListenerArray”之类的东西)[再次, 因为客户端正在选择它们]。您的查询更像是:

docsRef.where('ListenerArray', 'array-contains', clientID).onSnapshot((doc) => {
   handleSnapshot(doc);
   })

array-containssingle 值与 document 数组中的 all 条目进行检查,没有限制。每个客户端都可以标记要订阅的任意数量的文档。

【讨论】:

  • 嗯。 @TarikHuber,他提出了一个很好的观点:“如果您知道文档 ID,请听他们说”。但是您可以正确地想象,OP 想要那些 在查询中可表达 的特定文档是有原因的。我不喜欢将文档 ID 添加到文档中然后进行查询的想法。不妨采取其他答案。相反,我鼓励 OP 了解 why 这些文档并根据域特定属性查询它们。如果 OP 不能做到这一点,那么我会选择另一个答案,但我喜欢你的直觉。
  • @LeadDreamer 是的,10 的“in”限制太糟糕了。我不认为将“client”的值添加到数据中并执行“array-contains”的想法也可以在这里工作。我将要查找的文档列表是相当动态的。基本上,它是一个机场天气数据库。我正在根据是否有航班来/去动态生成机场列表。然后,我使用此列表仅提取我感兴趣的机场的天气,而不是全部获取。实际上,它不会超过 30 或 40 个机场。 30 或 40 位听众好吗?
  • @pilotGuy 这不是真正有问题的文档数量 - 您可以在 1000 上建立一个侦听器,但请注意,当您启动该侦听器时,您将阅读 all 其中 - 这是正在收听的客户数量。正如我所描述的,它将是每个客户端 一个 侦听器,侦听其 clientID 已添加到的每个文档。
  • @danh 如果您“知道 docID 只听它们”,则意味着每个文档都有一个听众 - 很多往返。至于将 docID 放入文档中 - 如果您要使用 docID,这是推荐的方法 - 您会发现查询 docID 很困难,原因有很多。 (见stackoverflow.com/a/58104104/2434784
  • @pilotGuy,您的评论开始提供使该答案成为正确答案的语义。查询计划类似于:给定航班,“获取”机场,给定机场,“听”天气。该计划不需要——也可能不应该——依赖于文档 ID。这些是——应该是——文档的可查询属性。不要订阅文档 ID,订阅查询。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-19
  • 2021-11-11
  • 2021-07-29
  • 2019-07-31
  • 2018-09-22
  • 2021-04-07
相关资源
最近更新 更多