Firestore:如何同时收听集合和子集合

Posted

技术标签:

【中文标题】Firestore:如何同时收听集合和子集合【英文标题】:Firestore: How to listen to both collection and subcollection 【发布时间】:2022-01-19 01:11:02 【问题描述】:

在 Firebase Firestore 中,我有一个集合,其中每个文档都包含一个 id 数组和一个子集合;像这样:

collection: households
>>> doc: household1, members = [1]
>>> >>> collection entries
>>> >>> >>> entry 1, <data>
>>> >>> >>> entry 2, <data>
>>> doc: household2, members = [1, 2]
>>> >>> collection entries
>>> >>> >>> entry 3, <data>
>>> >>> >>> entry 4, <data>
>>> >>> >>> entry 5, <data>

我想查询用户 1 所属的所有条目。我想对听众进行此操作,以便在 (1) 家庭发生变化或 (2) 条目发生变化时更新我的​​数据。

我该怎么做?

我试过先查询对应的户,然后得到对应的条目,像这样:

// Loop trough all households of user
db.collection("households")
  .where("members", "array-contains", uid)
  .where("status", "==", "active")
  .onSnapshot((snapshotChange) => 
    
    // Loop trough entry of each household
    snapshotChange.forEach((householdsDoc) => 
      db.collection("households")
        .doc(householdsDoc.id)
        .collection("entries")
        .onSnapshot((snapshotChange) => 
          snapshotChange.forEach((doc) => 
            // Prepare entry
            let currentDoc = doc.data();
            currentDoc["id"] = doc.id;
            // Handle change according to type
            snapshotChange.docChanges().forEach((change) => 
              console.log(change.type, "change.doc.id", change.doc.id);
              if (change.type === "added") 
                this.entries.push(currentDoc);
               else if (change.type === "modified") 
                let index = this.entries.findIndex(
                  (el) => el.id === change.doc.id
                );
                if (index > -1) 
                  this.entries.splice(index, 1);
                
                this.entries.push(currentDoc);
               else if (change.type === "removed") 
                let index = this.entries.findIndex(
                  (el) => el.id === change.doc.id
                );
                if (index > -1) 
                  this.entries.splice(index, 1);
                
              
            );
          );
        );

对于这段代码,我从控制台得到这个:

如您所见,不知何故,某些 id 会多次到达。这是为什么呢?

【问题讨论】:

【参考方案1】:

Firestore 中的读取和侦听器很浅。无法对家庭执行读取/查询,也无法一次性从子集合中获取条目。

您可以:

    对家庭集合执行查询,然后单独读取每个匹配家庭文档的子集合。 将成员数据复制到子集合中的每个条目文档中,然后use a collection group query 在所有条目集合中查询您需要的成员。

这两种方法都不比另一种更好,因此请查看您的具体用例,看看什么会产生最少的读取/成本和最佳性能。

【讨论】:

感谢您的澄清。我会选择你的第二个选项(尽管我仍然觉得复制数据很奇怪:P)。从好的方面来说,查询变得更加精简。非常感谢! 这实际上是 Julian 的权衡:更多的数据重复和更复杂的写入与更快和更简单的读取。 ? 一旦你习惯了这一点,就会突然发现,NoSQL 数据库往往在读取方面的技能非常出色,而在写入方面却不是那么好。

以上是关于Firestore:如何同时收听集合和子集合的主要内容,如果未能解决你的问题,请参考以下文章

如何从 Firestore 中删除集合或子集合?

如何使用 Flutter 获取 Firestore 中每个集合的子集合

如何在保持访问权限不变的同时将 Firestore 文档从一个子集合共享到另一个子集合?

FireStore 文档如何在子集合中读取计算

Firestore:获取带有和不带有子集合数据的集合[重复]

如何将子集合添加到 Firebase Cloud Firestore 中的文档