【问题标题】:Firestore multiple `in` queries with `and` logic, query structure [closed]使用“and”逻辑、查询结构Firestore多个“in”查询[关闭]
【发布时间】:2021-05-18 07:49:38
【问题描述】:

我正在开发一个带有 Firestore 数据库的 React 电子商务应用程序,其中客户应该能够过滤多种颜色(使用 OR 逻辑)和多种样式(使用 OR 逻辑)和多个品牌(使用 OR 逻辑)等,并且检索与这些过滤器匹配的前 50 个产品。

这里的主要限制是尽管使用.where("category", "==", "T-Shirts").where("color", "==", "Red") 链接多个等式是可能的,但firestore 查询(客户端或服务器)确实只允许单个“in”类型的查询。这意味着,如果用户想要查看 A 和 B 品牌的黑色或红色产品,则无法进行像 .where('color', 'in', ['Red', 'Black']).where('brand', 'in', ['A', 'B']) 这样的查询。请参阅https://firebase.google.com/docs/firestore/query-data/queries#query_limitationshttps://firebase.google.com/docs/firestore/query-data/queries#limitations_2 了解更多详情。

为了克服这个 Firestore 文档,建议使用两个不同的查询并在客户端处理数据。但是,在这种用例中没有提到分页,这意味着;

如果产品集合中有 1000 个文档,首先您必须以 .where('color', 'in', ['Red', 'Black']) 运行查询以获取结果,假设是 400 个文档,然后运行另一个查询 resultsOfFirstQuery.where('brand', 'in', ['A', 'B']).limit(50);,这将获取前 50 个文档,如果确实有50多个。

虽然这种方法看起来很简单,但实际上它会读取 400 个文档以便只显示其中的 50 个。如果用户更改单个过滤器字段,则这种类型的阅读会一次又一次地重复。为了克服这个问题,我已经想到了可能的解决方案;

  1. 获取与单个选择过滤器匹配的所有产品,例如类别(在我的情况下,客户只能设置一个类别字段)。并在客户端进行所有过滤。使用这种方法,应用程序仍会读取大量文档,但至少会在会话期间重复使用这些文档。

  2. 在服务器环境中运行多个查询,例如使用 Node.js 的云存储功能,并仅获取与所有过滤器匹配的前 50 个文档。使用这种方法,客户端只接收到想要的数据而不是更多,但服务器仍然读取很多。

  3. 限制每一步的查询,如果没有产品,用查询游标重新运行相同的查询。例如。 .where('color', 'in', ['Red', 'Black']).limit(50).startAfter(firstDoc) 并运行 resultsOfFirstQuery.where('brand', 'in', ['A', 'B']),如果有 5 个产品,则使用 startAfter(lastDocLastQuery) 重新运行查询,直到超过 50 个为止。使用这种方法,您仍然会阅读大量文档,但最终会逐渐将阅读次数从 50 增加到 50,直到您有 50 个产品匹配。

  4. 借助云功能在 Firebase 中创建自动化文档,例如Colors: {red:[product1ID,product2ID....], ....} 并根据过滤器在服务器端使用云功能获取相应的文档,创建匹配数组的叉积(AND 逻辑)并将其前 50 个元素推送到客户端。知道哪些产品要显示客户端然后处理获取客户端库。

这里还有其他我想念的方法吗?考虑到文档读取和客户端数据以及电池使用情况,您认为哪种方法是最好的方法?

我知道我的问题可以称为基于意见的问题,但这确实是个问题,我不想在每次出现导航时都获取数百个产品数据,即使在同一个会话中也是如此。我需要一种结合过滤、分页、存储本地数据的有效方法,但找不到适合上述问题范围的方法。

【问题讨论】:

  • 尽量将问题限制在一个主题上。在问题中添加多个问题将稀释答案并使它们成为文本墙。发布多个问题是您最好的选择。
  • 我将重新格式化内容并将反应位作为一个不同的问题发布,再次感谢您的审核。
  • 这取决于你的数据结构,这个问题更适合DBA exchange

标签: firebase google-cloud-firestore google-cloud-functions


【解决方案1】:

这是另一个选项:复合值

假设我们有三个制造商,每个制造商都有各种颜色

Manufacturer A
Manufacturer B
Manufacturer C

然后是三种颜色

Red
White
Blue

如果我们将数据存储在 Firestore 中的制造商和颜色等标准字段中,然后利用复合字段,则可以更轻松地执行多个 Or 查询

garment_0
   manufacturer: "Manufacturer A"
   color: "Red"
   compound: "A_R" //manufacture A, Red
garment_1
   manufacturer: "Manufacturer A"
   color: "White"
   compound: "A_W"
garment_2
   manufacturer: "Manufacturer B"
   color: "Blue"
   compound: "B_B"
garment_3
   manufacturer: "Manufacturer B"
   color: "White"
   compound: "B_W"

假设用户想要所有制造商 A 和 B 的白色或蓝色服装

garmentsRef.whereField("compound", in: ["A_W", "A_B", "B_W", "B_B"])

将退回服装_1(制造商 A,白色)、服装_2(制造商 B,蓝色)和服装_3(制造商 B,白色)

【讨论】:

  • 谢谢,我已经阅读了这个,它确实很有用,因为这些复合索引可以由云函数管理。然而,in 查询让您在数组中最多使用 10 个值。因此,在有 3-4 个过滤字段且每个过滤字段选择 2-3 个的情况下,这种方法需要再次进行多次查询。
  • @MelihAlan 不幸的是 Firestore 不支持联合或连接以防止多个查询,大多数情况下需要重组或使用代码变通方法来减少读取
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-07-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-08
  • 2018-07-14
  • 1970-01-01
相关资源
最近更新 更多