Présentation d'une requête avec filtres de plage et d'inégalité sur plusieurs champs
Firestore permet d'utiliser des filtres de plage et d'inégalité sur plusieurs champs dans une même requête. Vous pouvez définir des conditions de plage et d'inégalité sur plusieurs champs et simplifier votre le développement d'applications en déléguant l'implémentation de la logique post-filtrage dans Firestore.
Filtres de plage et d'inégalité sur plusieurs champs
La requête suivante utilise des filtres de plage sur la population et la densité pour renvoyer toutes villes dont la population est supérieure à 1 000 000 de personnes et la densité de la population est de moins de 10 000 personnes par unité de zone.
Modulaire version Web 9
const q = query(
collection(db, "cities"),
where('population', '>', 1000000),
where('density', '<', 10000),
);
Swift
let query = db.collection("cities")
.whereField("population", isGreaterThan: 1000000)
.whereField("density", isLessThan: 10000)
Objective-C
FIRQuery *query =
[[[[self.db collectionWithPath:@"cities"]
queryWhereField:@"population" isGreaterThan:@1000000]
queryWhereField:@"density" isLessThan:@10000];
Java Android
Query query = db.collection("cities")
.whereGreaterThan("population", 1000000)
.whereLessThan("density", 10000);
Kotlin + KTX Android
val query = db.collection("cities")
.whereGreaterThan("population", 1000000)
.whereLessThan("density", 10000)
Go
query := client.Collection("cities").
Where("population", ">", 1000000).
Where("density", "<", 10000)
Java
db.collection("cities")
.whereGreaterThan("population", 1000000)
.whereLessThan("density", 10000);
Node.js
db.collection("cities")
.where('population', '>', 1000000),
.where('density', '<', 10000)
Python
from google.cloud import firestore
db = firestore.Client()
query = db.collection("cities")
.where("population", ">", 1000000)
.where("density", "<", 10000)
PHP
C#
Ruby
query = cities_ref.where("population", ">", "1000000")
.where("density", "<", 10000)
C++
CollectionReference cities_ref = db->Collection("cities");
Query query = cities_ref.WhereGreaterThan("population", FieldValue::Integer(1000000))
.WhereLessThan("density", FieldValue::Integer(10000));
Unity
CollectionReference citiesRef = db.Collection("cities");
Query query = citiesRef.WhereGreaterThan("population", 1000000)
.WhereLessThan("density", 10000);
Dart
final citiesRef = FirebaseFirestore.instance.collection('cities')
final query = citiesRef.where("population", isGreaterThan: 1000000)
.where("density", isLessThan: 10000);
Remarques concernant l'indexation
Avant d'exécuter vos requêtes, consultez 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 les coûts des requêtes Firestore, optimiser l'ordre des champs dans l'index. Pour ce faire, assurez-vous que votre index est trié de gauche à droite afin que la requête se condense en un ensemble de données qui empêche l'analyse des entrées d'index inutiles.
Supposons que vous souhaitiez rechercher dans une collection d'employés ceux dont le salaire est supérieur à 100 000 $ et dont le nombre d'années d'expérience est supérieur à 0. D'après votre compréhension du jeu de données, vous savez que 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 [...])
Par conséquent, la requête rapide et économique consiste à trier 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 optimiser les 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 autres champs de l'index pour répondre aux autres contraintes de plage ou d'inégalité de la requête. Ces contraintes ne réduisent pas le nombre d'entrées d'index analysées par Firestore, mais elles filtrent les documents non mis en correspondance afin de réduire le nombre de documents renvoyés aux clients.
Pour en savoir plus sur la création d'index efficaces, consultez la section Propriétés d'index.
Classer les champs par ordre décroissant de sélectivité de la contrainte 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. Assurez-vous de sélectionner les champs de plage ou d'inégalité avec une sélectivité plus élevée plus tôt dans l'ordre d'index que les champs avec une sélectivité plus faible.
Pour réduire le nombre de documents que Firestore analyse et renvoie sur le réseau, vous devez toujours trier les champs par ordre décroissant de sélectivité des contraintes de requête. Si l'ensemble de résultats n'est pas dans l'ordre requis et qu'il est censé être de petite taille, vous pouvez implémenter une logique côté client pour le réorganiser conformément à vos attentes.
Par exemple, supposons que vous souhaitiez effectuer une recherche dans un ensemble d'employés pour trouver Employés des États-Unis dont le salaire est supérieur à 100 000 $et ordonnent les résultats par année du de l'expérience de l'employé. Si vous prévoyez que seuls un petit nombre d'employés auront un salaire supérieur à 100 000 $, le moyen le plus efficace d'écrire la requête est le suivant :
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`
Bien que l'ajout d'un tri sur experience
à la requête génère le même ensemble de documents et évite 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 préfère toujours un indice dont le préfixe de champ d'index correspond à la clause "order by" 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. Comme il n'y a pas d'autres contraintes sur experience
, Firestore lit toutes les entrées d'index de la collection employees
avant d'appliquer le filtre salary
pour trouver l'ensemble de résultats final. 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 avec des filtres de plage et d'inégalité sur plusieurs champs sont facturées en fonction des documents lus et des entrées d'index lus.
Pour en savoir plus, consultez la page Tarifs.
Limites
En plus des limites des requêtes, tenez compte des limites suivantes avant d'utiliser des requêtes avec des filtres de plage et d'inégalité sur plusieurs champs :
- Les requêtes avec des filtres de plage ou d'inégalité sur les champs de document et uniquement des contraintes d'égalité sur la clé de document
(__name__)
ne sont pas acceptées. - 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
- Découvrez comment optimiser vos requêtes.
- Découvrez comment exécuter des requêtes simples et composées.
- Découvrez comment Firestore utilise les index.