web-dev-qa-db-fra.com

Firestore: plusieurs 'contient-tableau'

J'essaie de filtrer les données avec plusieurs méthodes where() à l'aide de array-contains opérateur, mais j'ai l'erreur suivante:

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

Fondamentalement, j'ai une collection contenant les documents suivants:

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

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

Ensuite, j'ai mon tableau avec les articles que je souhaite trouver dans la base de données:

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

Je veux rechercher sku4 et sku2, s'il en trouve, renvoie l'objet.

Mon problème est que array-contains n'est pas autorisé à s'exécuter plusieurs fois.

Voici le code que j'utilise pour filtrer:

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

Comme vous le constatez, mon problème est que je fais une boucle dans mon tableau list, mais mon ref génère une erreur car je lance plusieurs fois "array-contains".

J'ai également essayé de comparer avec le tableau:

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

qui n'en retourne pas, je crois que array-contains ne se compare pas aux tableaux, seulement des chaînes/nombres/booléens peut-être?

Quelqu'un connaît-il une solution pour cela sans avoir à les interroger individuellement?

Je vous remercie

6
gugateider

Une solution serait de stocker les "balises" dans un objet en tant que noms de propriété.

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

Ensuite, vous pouvez créer les clauses AND WHERE comme ceci:

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

Cette approche est une réponse à la question "sans avoir à les interroger individuellement". Cependant, dès que vous souhaitez commander et paginer, vous rencontrerez un autre mur de briques invisible d'indices composés.

10
mrnagydavid

Comme vous l'avez constaté, vous ne pouvez avoir qu'un seul array-contains opération dans une requête. L'idée d'autoriser plusieurs n'est actuellement pas prise en charge, mais pourrait être valide. Je vous recommande donc déposer une demande de fonctionnalité .

La seule solution à laquelle je peux penser pour votre cas d'utilisation en ce moment, est également d'inclure les combinaisons. Donc, si vous souhaitez autoriser le test de l'existant de deux références, vous explosez le tableau pour qu'il contienne également chaque combinaison (fusion des clés dans l'ordre lexicographique):

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

Pour deux, cela pourrait encore être raisonnable, mais l'explosion combinatoire la rendra irréalisable au-delà de cela.

6
Frank van Puffelen