使用“和"逻辑将查询中的内容存储在Firestore中,查询结构 [英] Firestore multiple `in` queries with `and` logic, query structure

查看:28
本文介绍了使用“和"逻辑将查询中的内容存储在Firestore中,查询结构的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发一个具有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","==",红色")是可能的,firestore查询(客户端或服务器)确实只允许单个输入".查询类型.这意味着,如果用户希望看到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中)在Firebase中创建自动文档颜色:{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)

这篇关于使用“和"逻辑将查询中的内容存储在Firestore中,查询结构的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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