firebase Firestore:多个“数组包含”

klsxnrf1  于 2022-12-24  发布在  其他
关注(0)|答案(5)|浏览(166)
    • 关于这个问题的最新情况**

Firestore启动了另一个类似于in查询的特性,array-contains-any查询,该特性允许您同时对多个值执行array-contains查询。
使用array-contains-any运算符可以使用逻辑OR组合同一字段上的最多10个array-contains子句。array-contains-any查询将返回给定字段是包含一个或多个比较值的数组的文档:
第一个月
Firestore-阵列包含任何

    • 问题**

我尝试使用array-contains运算符通过多个where()方法过滤数据,但出现以下错误:

An error occured: Error: 3 INVALID_ARGUMENT: 
A maximum of 1 'ARRAY_CONTAINS' filter is allowed.

基本上,我有一个包含以下文档的集合:

product1 
  - node_sku ['sku1', 'sku2', 'sku3' ]

product2 
  - node_sku ['sku4', 'sku5', 'sku6' ]

然后,我有了一个数组,其中包含我希望在数据库中找到的项目:

const list = ['sku4', 'sku2']

我想搜索sku4sku2,如果找到任何返回对象。
我的问题是array-contains不允许运行超过一次。
下面是我用来过滤的代码:

const list = ['sku4', 'sku2'];

let database = firestore_db.collection('glasses');
let ref = database;

list.forEach( (val) => { 
    ref = ref.where('node_sku' , 'array-contains' , val);
});
ref.get() 
.then( (snapshot) => glassesRequestComplete(snapshot, req, response))
.catch( (error) => glassesRequestError(error, response) );

正如您所注意到的,我的问题是我在list数组中循环,但是ref抛出了一个错误,因为我不止一次地触发了'array-contains'。
我还尝试与数组进行比较:

ref.where('node_sku' , 'array-contains' , list);

它不返回任何值,我相信arrays-contains不与数组进行比较,可能只与字符串/数字/布尔值进行比较?
有没有人知道一个解决方案,而不必单独查询他们?
谢谢

t1qtbnec

t1qtbnec1#

一种解决方案是将“标记”作为对象的属性名存储在对象中。

node_sku = {
  "sku1": true,
  "sku2": true,
  ...
  "skun": true
}

然后,您可以创建AND WHERE子句,如下所示:

list.forEach( (val) => { 
  ref = ref.where(`node_sku.${val}` , '==' , true);
});

这种方法回答了“不必单独查询它们”的问题。然而,一旦您想要排序和分页,您就会遇到另一堵看不见的复合索引砖墙。

9vw9lbht

9vw9lbht2#

正如你所发现的,在一个查询中你只能有一个array-contains操作。允许多个操作的想法目前还不被支持,但是可能是有效的。所以我推荐你使用file a feature request
对于您的用例,我现在能想到的唯一解决方案是也包含组合,所以如果您想允许测试两个SKU的存在,您可以分解数组以包含每个组合(按字典顺序合并键):

product1 
  - node_sku ['sku1', 'sku2', 'sku3', 'sku1_sku2', 'sku1_sku3', 'sku2_sku3' ]

对于两个人来说,这可能仍然是合理的,但组合爆炸将使它不可行超过这一点。

w8biq8rn

w8biq8rn3#

Firestore启动了另一个类似于in查询的特性,array-contains-any查询,该特性允许您同时对多个值执行array-contains查询。

ref = ref.where('node_sku' , 'array-contains-any' , list);

Firestore-阵列包含任何

11dmarpk

11dmarpk4#

可以这样说:

ref.where("node_sku", "in", list).get()
.then((snapshot) => glassesRequestComplete(snapshot, req, response)).catch( (error) => glassesRequestError(error, response) );
rwqw0loc

rwqw0loc5#

我的解决方案是使用'array-contains-any'提取所有项,然后使用lodash _.intersection()查找与所有项匹配的项,它也适用于单个项搜索。

const searchTerms = searchKey.split(" ");
      const searchTermCount = searchTerms.length;
      const productsRef = collection(this.db, "products");
      const termsQuery = query(productsRef,
            where("search", "array-contains-any", searchTerms),
            orderBy("popularity", "desc"),
            orderBy("name_lower"),
            limit(resultLimit));

        const snaps = await getDocs(termsQuery);   
        let products = [];
             
        snaps.forEach((doc) => {
          const p = doc.data();
          const allTerms = _.intersection(p.search, searchTerms).length === searchTermCount;
          if (allTerms)
            products.push(p);
      });

相关问题