使用“and"逻辑、查询结构Firestore多个“in"查询 [英] Firestore multiple `in` queries with `and` logic, query structure

查看:15
本文介绍了使用“and"逻辑、查询结构Firestore多个“in"查询的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I`m developing a react e-commerce app with firestore database where a customer should be able to filter multiple colors (with OR logic) AND multiple styles (with OR logic) AND multiple brands (with OR logic) etc. and retrieve first 50 products matching these filters.

这里的主要限制是尽管使用 .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_limitations &https://firebase.google.com/docs/firestore/query-数据/查询#limitations_2了解更多详情.

The main constraint here is that although chaining multiple equalities by using .where("category", "==", "T-Shirts").where("color", "==", "Red") is possible, firestore queries (client or server) does allow only single "in" type of queries. That means if a user wants to see black or red products of A and B brands a query like .where('color', 'in', ['Red', 'Black']).where('brand', 'in', ['A', 'B']) is not possible. See https://firebase.google.com/docs/firestore/query-data/queries#query_limitations & https://firebase.google.com/docs/firestore/query-data/queries#limitations_2 for more details.

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

To overcome this Firestore docs recommends using two different queries and dealing with data on the client side. However there is no mention of pagination in such use case and it means;

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

If there are 1000 documents in a product collection, first you have to run a query as .where('color', 'in', ['Red', 'Black']) get the results, let`s say 400 documents, and run another query resultsOfFirstQuery.where('brand', 'in', ['A', 'B']).limit(50);, this would fetch first 50 documents if there are indeed more than 50.

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

While this approach seems straightforward, it actually reads 400 document in order to just display 50 of them. More if a user changes single filter field this type of reading repeats again and again. To overcome this, I already thought of possible solutions;

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

  1. Fetch all the products matching a single selection filter e.g. category (in my case a customer can only set a single category field). And do all the filtering on the client side. With this approach the app still reads lots of documents but at least reuse these during the session time.

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

Run multiple queries in a server environment, such as cloud store functions with Node.js and get only the first 50 documents that are matching all the filters. With this approach client only receives wanted data not more, but server still reads a lot.

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

Limit the queries at each step, and if there aren`t products, rerun the same queries with query cursors. E.g. .where('color', 'in', ['Red', 'Black']).limit(50).startAfter(firstDoc) and run resultsOfFirstQuery.where('brand', 'in', ['A', 'B']), if there are 5 products rerun the query with startAfter(lastDocLastQuery) until you have more than 50. With this approach you still read lots of documents but you end up gradually increasing the reads 50 by 50 until you have 50 products matching.

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

Create automated documents in firebase with the help of cloud functions, e.g. Colors: {red:[product1ID,product2ID....], ....} and depending on filters get corresponding documents in server side with cloud functions, create a cross product of matching arrays (AND logic) and push first 50 elements of it to the client side. Knowing which products to display client then handle fetching client side library.

还有其他我想念的方法吗?考虑到文档中的内容,您认为哪种方法最好?客户端数据和电池使用情况?

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

I know that my question can be referred as opinion based, but it's really a problem, I don't want to fetch hundreds of products data each time a navigation occurs even within the same session. I need an effective way combining filtering, paginating, storing local data and could not find a way that fits the scope of my problem above.

推荐答案

这是另一个选项:复合值

Here's another option: compound values

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

Suppose we have three manufacturers and each has a variety of colors

Manufacturer A
Manufacturer B
Manufacturer C

然后是三种颜色

Red
White
Blue

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

If we store our data in Firestore in both standard fields like manufacturer and color and then leverage a compound field, it makes doing multiple Or queries much easier

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 的白色或蓝色服装

Suppose the user wants all manufacturer A and B's garments that are White or Blue

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

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

Would return garment_1 ( Manufacturer A, White), garment_2 (Manufacturer B, Blue) and garment_3 (Manufacturer B, White)

这篇关于使用“and"逻辑、查询结构Firestore多个“in"查询的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆