Présentation d'une requête avec filtres de plage et d'inégalité sur plusieurs champs

Firestore accepte l'utilisation de filtres de plage et d'inégalité sur plusieurs champs dans une seule requête. Vous pouvez maintenant avoir la plage et des conditions d'inégalité sur plusieurs champs et simplifier le développement d'applications en déléguant l'implémentation de la logique post-filtrage et Firestore.

Filtres de plage et d'inégalité sur plusieurs champs

La requête suivante renvoie tous les utilisateurs dont l'âge est supérieure à 35 et la hauteur est comprise entre 60 et 70 en utilisant des filtres de plage sur l’âge et la taille.

Modulaire version 9 sur le Web

  const q = query(
      collection(db, "users"),
      where('age', '>', 35),
      where('height', '>', 60),
      where('height', '<', 70)
    );

Swift

 let query = db.collection("users")
   .whereField("age", isGreaterThan: 35)
   .whereField("height", isGreaterThan: 60)
   .whereField("height", isLessThan: 70)

Objective-C

 FIRQuery *query = 
  [[[[self.db collectionWithPath:@"users"]
 queryWhereField:@"age" isGreaterThan:@35]
    queryWhereField:@"height" isGreaterThan:@60] 
        queryWhereField:@"height" isLessThan:@70];

Java pour Android

 Query query = db.collection("users")
  .whereGreaterThan("age", 35)
  .whereGreaterThan("height", 60)
  .whereLessThan("height", 70);

Kotlin+KTX Android

 val query = db.collection("users")
  .whereGreaterThan("age", 35)
  .whereGreaterThan("height", 60)
  .whereLessThan("height", 70)

Java

  db.collection("users")
    .whereGreaterThan("age", 35)
    .whereGreaterThan("height", 60)
    .whereLessThan("height", 70);

Node.js

db.collection("users")
  .where('age', '>', 35),
  .where('height', '>', 60),
  .where('height', '<', 70)

Remarques concernant l'indexation

Avant de commencer à exécuter vos requêtes, assurez-vous d'avoir lu sur les requêtes et le modèle de données de Firestore.

Dans Firestore, la clause ORDER BY d'une requête détermine les index peut servir à répondre à la requête. Par exemple, une requête ORDER BY a ASC, b ASC nécessite un index composite sur les champs a ASC, b ASC.

Pour optimiser les performances et le coût des requêtes Firestore, vous devez optimiser l'ordre des champs dans l'index. Pour ce faire, vous devez vous assurer que votre index est ordonné de gauche à de sorte que la requête soit transmise à un ensemble de données qui empêche l'analyse des entrées d'index superflues.

Supposons que vous souhaitiez effectuer une recherche dans un ensemble d'employés et trouver employés dont le salaire est supérieur à 100 000 et dont le nombre d'années d'expérience est supérieure à 0. D'après votre compréhension de l'ensemble de données, la contrainte de salaire est plus sélective que la contrainte d’expérience. L'idéal permettant de réduire le nombre d'analyses d'index (salary [...], experience [...]) Ainsi, la requête qui serait rapide la plus rentable commanderait salary avant experience et se présente comme suit:

Java

db.collection("employees")
  .whereGreaterThan("salary", 100000)
  .whereGreaterThan("experience", 0)
  .orderBy("salary")
  .orderBy("experience");

Node.js

db.collection("employees")
  .where("salary", ">", 100000)
  .where("experience", ">", 0)
  .orderBy("salary")
  .orderBy("experience");

Python

db.collection("employees")
  .where("salary", ">", 100000)
  .where("experience", ">", 0)
  .order_by("salary")
  .order_by("experience");

Bonnes pratiques pour l'optimisation des index

Lorsque vous optimisez des index, tenez compte des bonnes pratiques suivantes.

Classer les champs d'index par égalité, suivi de la plage la plus sélective ou du champ d'inégalité

Firestore utilise les champs les plus à gauche d'un index composite pour satisfaire aux les contraintes d'égalité et la contrainte de plage ou d'inégalité, le cas échéant, sur le premier champ. de la requête orderBy(). Ces contraintes peuvent réduire le nombre entrées analysées par Firestore. Firestore utilise les champs restants de l'index pour satisfaire aux autres contraintes de plage ou d'inégalité de la requête. Ces ne réduisent pas le nombre d'entrées d'index analysées par Firestore mais filtrer les documents sans correspondance afin que le nombre de documents renvoyés aux clients sont réduits.

Pour en savoir plus sur la création d'index efficaces, consultez la définition d'un index parfait.

Classer les champs par ordre décroissant de sélectivité des contraintes de requête

Pour vous assurer que Firestore sélectionne l'index optimal pour votre requête, spécifier une clause orderBy() qui classe les champs par ordre décroissant de requête la sélectivité des contraintes. Une plus grande sélectivité correspond à un sous-ensemble plus petit documents, tandis qu'une sélectivité inférieure correspond à un sous-ensemble plus important de documents. Vérifiez que vous sélectionnez des champs de plage ou d'inégalité avec une sélectivité plus élevée plus tôt dans l'index que les champs avec une sélectivité moindre.

À réduire le nombre de documents analysés et renvoyés par Firestore réseau, vous devez toujours classer les champs dans l'ordre décroissant des la sélectivité des contraintes. Si l'ensemble de résultats n'est pas dans l'ordre requis et si l'ensemble de résultats attendu est limité, vous pouvez implémenter une logique côté client pour commander à nouveau selon vos attentes.

Par exemple, supposons que vous souhaitiez effectuer une recherche dans un ensemble d'employés pour trouver employés dont le salaire est supérieur à 100 000 et ordonner les résultats par année de de l'expérience de l'employé. Si vous pensez que seul un petit nombre d'employés aura un salaire supérieur à 100 000, la méthode la plus efficace pour écrire la requête est la suivante:

Java

db.collection("employees")
  .whereGreaterThan("salary", 100000)
  .orderBy("salary")
  .get()
  .addOnSuccessListener(new OnSuccessListener<QuerySnapshot>() {
        @Override
        public void onSuccess(QuerySnapshot queryDocumentSnapshots) {
          // Order results by `experience`
        }
    });;

Node.js

const querySnapshot = await db.collection('employees')
                              .where("salary", ">", 100000)
                              .orderBy("salary")
                              .get();

// Order results by `experience`

Python

results = db.collection("employees")
            .where("salary", ">", 100000)
            .order_by("salary")
            .stream()

// Order results by `experience`

Alors que l'ajout d'un tri sur experience à la requête permet d'obtenir le même ensemble de documents et éviter de réorganiser les résultats sur les clients, la requête peut lire beaucoup plus d'entrées d'index superflues que la requête précédente. En effet, Firestore privilégie toujours un index dont le préfixe des champs d'index correspond au préfixe classer par clause de la requête. Si vous avez ajouté experience à la clause order by : Firestore sélectionne ensuite l'index (experience [...], salary [...]) pour calculer les résultats d'une requête. Puisqu'il n'y a pas d'autres contraintes experience, Firestore lit toutes les entrées d'index de la employees avant d'appliquer le filtre salary pour trouver le résultat final ensemble de résultats. Cela signifie que les entrées d'index qui ne répondent pas aux critères salary sont tout de même lues, ce qui augmente la latence et le coût de la requête.

Tarifs

Les requêtes comportant des filtres de plage et d'inégalité sur plusieurs champs sont facturées en fonction documents lus et entrées d’index lues.

Pour en savoir plus, consultez la page Tarifs.

Limites

En plus des limites applicables aux requêtes, notez les limitations suivantes en utilisant des requêtes avec des filtres de plage et d'inégalité sur plusieurs champs:

  • Requêtes avec des filtres de plage ou d'inégalité sur les champs de document et uniquement d'égalité Les contraintes appliquées à la clé de document (__name__) ne sont pas prises en charge.
  • Firestore limite le nombre de champs de plage ou d'inégalité à 10. Cela permet d'éviter que les requêtes ne deviennent trop coûteuses s'exécuter.

Étape suivante