Firestore: Multiple 'array-contains'

I am trying to filter data with multiple where() methods using the array-contains operator, however I am having the following error:

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

Basically, I have a collection containing the following docs:

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

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

Then I have my array with items I wish to find on the database:

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

I want to search for sku4 and sku2, if finds any returns the object.

My problem is that array-contains is not allowed to run more than once.

Here's the code I am using to filter:

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) );

As you notice, my problem is that I am looping through my list array, however my ref is throwing an error since I am firing 'array-contains' more than once.

I have also tried to compare against the array:

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

which does not return any , I believe array-contains does not compare against arrays, only strings/numbers/booleans maybe?

Does anybody know a solution for that without having to query them individually?

Thank you

Answers:

Answer

One solution would be to store the 'tags' in an Object as its property names.

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

Then you can create the AND WHERE clauses like this:

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

This approach is an answer to the question "without having to query them individually". However, as soon as you want ordering and pagination, you will run into another invisible brick wall of compound indices.

Answer

As you've found you can only have a single array-contains operation in a query. The idea of allowing multiple is currently not supported, but could be valid. So I recommend you file a feature request.

The only solution I can think of for your use-case right now, is to also include the combinations. So if you want to allow testing for the existing of two SKUs, you explode the array to also contain each combination (merging keys in lexicographical order):

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

For two that might still be reasonable, but the combinatory explosion will make it infeasible beyond that.

Tags

Recent Questions

Top Questions

Home Tags Terms of Service Privacy Policy DMCA Contact Us

©2020 All rights reserved.