【问题标题】:How do I fetch documents with specific ids (plural) from a firestore collection using the `in` clause?如何使用 `in` 子句从 firestore 集合中获取具有特定 ID(复数)的文档?
【发布时间】:2021-04-06 13:23:51
【问题描述】:

我已经阅读了一些关于该主题的帖子,但由于某种原因,我无法获取我需要的文档。我有一个带有自动生成 ID 的集合 users,每个文档都包含名称和电子邮件。这是我的收藏:

请注意,ID 是自动生成的。

然后,我尝试在代码中执行以下操作:

firebase.firestore()
        .collection("users")
        .where(
          "id",
          "in",
          ids
        )
        .get()
        .then((querySnapshot) => {
            const people = [];
            querySnapshot.forEach(documentSnapshot => {
              people.push({
                  ...documentSnapshot.data(),
                  key: documentSnapshot.id
                  });
                });
              console.log("people: ", people);
          });

我的 people 数组是空的。我很确定我的 ids 数组具有正确的 ID。我不确定这部分是否正确:

firebase.firestore()
        .collection("users")
        .where(
          "id",
          "in",
          ids
        )
        .get()

"id" 是自动生成列的正确名称吗?

【问题讨论】:

    标签: javascript firebase react-native google-cloud-firestore


    【解决方案1】:

    要通过文档 ID 查询文档,您应该使用 firebase.firestore.FieldPath.documentId(),它返回一个特殊值,可与 where() 过滤器一起使用以通过文档 ID 进行搜索。


    以下代码已从 this documented gist (Typescript/JavaScript) 调整:

    function chunkArr(arr, n) {
      if (n <= 0) throw new Error("n must be greater than 0");
      return Array
        .from({length: Math.ceil(arr.length/n)})
        .map((_, i) => arr.slice(n*i, n*(i+1)))
    }
    
    async function fetchDocumentsWithId(collectionQueryRef, arrayOfIds) {
      // in batches of 10, fetch the documents with the given ID from the collection
      const fetchDocsPromises = chunkArr(arrayOfIds, 10)
        .map((idsInChunk) => (
          collectionQueryRef
            .where(firebase.firestore.FieldPath.documentId(), "in", idsInChunk)
            .get()
        ))
    
      return Promise.all(fetchDocsPromises)
        .then((querySnapshotArray) => {
          const allDocumentsArray = [];
          for (let querySnapshot of querySnapshotArray) {
            querySnapshot.forEach(doc => allDocumentSnapshotsArray.push({...doc.data(), key: doc.id}))
          }
          return allDocumentsArray;
        });
    }
    
    const usersColRef = firebase.firestore()
            .collection("users");
    const ids = [ /* ... */ ];
    
    const docDataArray = fetchDocumentsWithId(usersColRef, ids);
    

    如果您要使用未经编辑的the gist 版本,您可以改用:

    
    const usersColRef = firebase.firestore()
            .collection("users");
    const ids = [ /* ... */ ];
    const docDataArray = [];
    
    await fetchDocumentsWithId(usersColRef, ids, (doc) => docDataArray.push({ ...doc.data(), key: doc.id }))
    
    console.log(docDataArray)
    

    注意:我会避免在 Firestore 中使用术语“key”,而是使用“id”。如果您在文档中使用“id”,则始终可以使用“_id”。

    【讨论】:

    • 您需要查看 firebase.firestore.FieldPath.documentId() 创建的值的一些限制 - 它返回文档的完整路径,而不仅仅是特定的 documentId stackoverflow.com/a/58104104/2434784跨度>
    • @LeadDreamer 我不确定什么时候,但是这个问题已经解决了,因为这个答案已经发布,因为这里包含的代码可以按预期工作。我会看看我是否能找到一些关于何时/如何修复此问题的信息,这应该是 2020 年 1 月至 6 月之间的某个时间。
    • @LeadDreamer 继我之前的评论之后,firebase.firestore.FieldPath.documentId() 有两种模式。在 CollectionReference 上使用时,您只需指定文档 ID(例如 "c90QMzGbPSJA1qiQ95f6")。但是,当用于集合组查询时,您指定一个有效的文档路径(例如"users/Ddy1QVOAO6SIvB8LfAE8Z0Adj4H3/todos/c90QMzGbPSJA1qiQ95f6")。这似乎是有意的based on the SDK tests
    • 感谢您的提及,当有关此功能的文档不可用时,我将确保使用此信息更新要点。
    【解决方案2】:

    在这种情况下,我假设 ids 是您在客户端代码中拥有的一个数组,并且只想在 firestore 中查询这些 id?

    不幸的是,在 firestore 中使用 .where() 功能时,它不会查询文档 ID,而是查询文档的内容。

    如果您想使用 firestore 的 .where() 索引功能,您需要在实际文档数据中添加一个 uid 字段。一旦你这样做了,你应该能够只查询你想要的 ID。

    From the firestore docs

    【讨论】:

    • 我明白了。这不是一个坏习惯吗?我的意思是,我有一次ID,然后我第二次输入它们。或者这是一种标准做法? Tbh,我找不到任何“简单”的方法来获取我数组中的文档,除了 for 循环和一一查询?
    • 另外,我认为该列名为“id”是否正确?
    • 在 Firestore 等 NoSQL 数据结构中,数据的非规范化(重复)并不是坏习惯。不,您不能查询超出 firestore.collection('users').doc(&lt;docId&gt;) 的文档 ID。
    • @cpboyce 令人讨厌的是,guide documentation 中没有提到它,但自 Firestore SDK 的 v0.1.1 以来一直存在 (Release Notes/GitHub Changelog)。之所以遇到它,是因为它终于在去年六月添加到documented API Reference
    • 这不是指南中唯一未更新的内容。该指南尚未更新以说明批量写入不计入field transforms as two operations anymore
    猜你喜欢
    • 2023-03-03
    • 2021-02-16
    • 1970-01-01
    • 1970-01-01
    • 2018-04-04
    • 1970-01-01
    • 2021-07-17
    • 2019-09-17
    • 2021-02-01
    相关资源
    最近更新 更多