Firebase 查询“IN”限制为 10 是否有解决方法?

Oli*_*via 23 firebase react-native google-cloud-firestore

我有一个对 Firebase 的查询,其中包含一个大小 > 10 的 ID 数组。 Firebase 对一个会话中要查询的记录数有限制。有没有办法一次查询超过 10 个?

[未处理的承诺拒绝:FirebaseError:无效查询。'in' 过滤器支持值数组中最多 10 个元素。]

https://cloud.google.com/firestore/docs/query-data/queries

在此处输入图片说明

  let query = config.db
    .collection(USER_COLLECTION_NAME)
    .where("id", "in", matchesIdArray);
  const users = await query.get();
Run Code Online (Sandbox Code Playgroud)

(matchesIdArray.length 需要是无限的)

小智 12

我发现这对我来说效果很好,而无需进行尽可能多的查询(循环和请求批量为 10)。

export function getContentById(ids, path) {
  return new Promise((res) => {
    // don't run if there aren't any ids or a path for the collection
    if (!ids || !ids.length || !path) return res([]);

    const collectionPath = db.collection(path);
    let batches = [];

    while (ids.length) {
      // firestore limits batches to 10
      const batch = ids.splice(0, 10);

      // add the batch request to to a queue
      batches.push(
        new Promise(response => {
          collectionPath
            .where(
              firebase.firestore.FieldPath.documentId(),
              'in',
              [...batch]
            )
            .get()
            .then(results => response(results.docs.map(result => ({ ...result.data()}) )))
        })
      )
    }

    // after all of the data is fetched, return it
    Promise.all(batches).then(content => {
      res(content.flat());
    })

  })
}
Run Code Online (Sandbox Code Playgroud)


Ana*_*eem 6

最佳方法

将列表转换为每个包含 10 个项目的子列表的列表。然后 for 循环遍历第二个列表并在每个循环中通过 firebase 进行查询。

例子:

List<String> phoneNumbers = ['+12313','+2323','1323','32323','32323','3232', '1232']; //CAN BE UPTO 100 or more
Run Code Online (Sandbox Code Playgroud)

将电话号码转换为每个包含 10 项的子列表

List<List<String>> subList = [];
for (var i = 0; i < phoneNumbers.length; i += 10) {
    subList.add(
        phoneNumbers.sublist(i, i + 10> phoneNumbers.length ? phoneNumbers.length : i + 10));
}
Run Code Online (Sandbox Code Playgroud)

现在运行 Firebase 查询

subList.forEach((element) {
      firestore
          .collection('Stories')
          .where('userPhone', whereIn: element)
      .get()
      .then((value) {
    
    value.docs.forEach((snapshot) {
      //handle the list
    });

  });
Run Code Online (Sandbox Code Playgroud)


Dou*_*son 5

您唯一的解决方法是对通常与单个“in”查询一起使用的数组中的每个项目进行一次查询。或者,批处理数组中的请求。

  let query = config.db
    .collection(USER_COLLECTION_NAME)
    .where("id", "==", matchesIdArray[0]);
  const users = await query.get();
Run Code Online (Sandbox Code Playgroud)

您必须在matchesIdArray数组上循环使用上述代码,并在完成后合并结果。


Fra*_*len 5

解决此限制的一种常见方法是批量检索项目,然后顺序或并行处理每个查询的结果。

另一种常见的解决方法是以一种不需要您阅读数十个文档来处理用户的单独请求的方式对数据进行建模。很难说如何减少这个数字,但它通常涉及将这些单独文档中所需的数据复制到单个聚合文档中。

举个例子:如果您有一个新闻网站,需要显示 5 个类别中每个类别的最新 10 篇文章标题,您可以执行以下操作:

  1. 进行 50 次单独读取,每个文档一次。
  2. 创建一个文档,其中包含最新 10 篇文章的标题,然后只需要阅读 5 个文档(每个类别一个)。
  3. 创建包含所有 5 个类别的最新 10 个标题的文档,然后只需要阅读该文档。

在最后两个场景中,您将使写入数据库的代码变得更加复杂,因为它现在也需要写入聚合文档。但作为回报,您需要读取的数据要少得多,这降低了成本,并提高了应用程序的性能。在使用 NoSQL 数据库时,这种类型的权衡非常常见,这种数据库往往用于数据读取量远多于写入量的场景。

有关更多数据建模建议,我建议: