Cloud Firestore est compatible avec l'utilisation de filtres de plage et d'inégalité sur plusieurs champs dans une seule requête. Vous pouvez appliquer des conditions de plage et d'inégalité à plusieurs champs et simplifier le développement de votre application en déléguant l'implémentation de la logique de post-filtrage à Cloud 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 les villes où la population est supérieure à 1 000 000 d'habitants et la densité de population est inférieure à 10 000 habitants par unité de surface.
Version Web 9 modulaire
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);
Considérations relatives à l'indexation
Avant d'exécuter vos requêtes, découvrez les requêtes et le Cloud Firestore modèle de données.
Dans Cloud Firestore, la clause ORDER BY d'une requête détermine les index
qui peuvent être utilisés pour la traiter. 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 Cloud Firestore, optimisez l'ordre des champs dans l'index. Pour ce faire, assurez-vous que votre index est trié de gauche à droite de sorte que la requête se limite à un ensemble de données qui empêche l'analyse des entrées d'index inutiles.
Supposons que vous souhaitiez effectuer une recherche dans une collection d'employés et trouver les employés aux États-Unis dont le salaire est supérieur à 100 000 $ et dont le nombre d'années d'expérience est supérieur à 0. En fonction de votre compréhension de l'ensemble de données, vous savez que la contrainte de salaire est plus sélective que la contrainte d'expérience. L'index idéal qui réduirait le nombre d'analyses d'index serait (salary [...], experience [...]). Ainsi, la requête rapide et économique classerait salary avant experience et se présenterait 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.
Trier les champs d'index par égalités, puis par le champ de plage ou d'inégalité le plus sélectif
Cloud Firestore utilise les champs les plus à gauche d'un index composite pour satisfaire les
contraintes d'égalité et la contrainte de plage ou d'inégalité, le cas échéant, sur le premier champ
de la orderBy() requête. Ces contraintes peuvent réduire le nombre d'entrées d'index
analysées par Cloud Firestore Cloud Firestore utilise les champs restants
de l'index pour satisfaire d'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 Cloud Firestore mais filtrent les documents non correspondants 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 des index.
Trier les champs par ordre décroissant de sélectivité des contraintes de requête
Pour vous assurer que Cloud Firestore sélectionne l'index optimal pour votre requête,
spécifiez une clause orderBy() qui trie les champs par ordre décroissant de sélectivité des contraintes de requête. Une sélectivité plus élevée correspond à un sous-ensemble de documents plus petit, tandis qu'une sélectivité plus faible correspond à un sous-ensemble de documents plus grand. Assurez-vous de sélectionner les champs de plage ou d'inégalité avec une sélectivité plus élevée plus tôt dans le tri des index que les champs avec une sélectivité plus faible.
Pour minimiser le nombre de documents que Cloud 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 petit, vous pouvez implémenter une logique côté client pour le réorganiser selon vos attentes.
Supposons, par exemple,que vous souhaitiez effectuer une recherche dans une collection d'employés pour trouver les employés aux États-Unis dont le salaire est supérieur à 100 000 $ et trier les résultats par année d'expérience de l'employé. Si vous vous attendez à ce qu'un petit nombre d'employés aient un salaire supérieur à 100 000 $, la manière la plus efficace d'é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`
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,
Cloud Firestore préfère toujours un index dont le préfixe des champs d'index correspond à la
clause "order by" de la requête. Si experience était ajouté à la clause "order by",
alors Cloud Firestore sélectionnera l'index (experience [...], salary [...])
pour calculer les résultats de la requête. Comme il n'y a pas d'autres contraintes sur
experience, Cloud Firestore lira toutes les entrées d'index de la
employees collection avant d'appliquer le salary filtre pour trouver l'ensemble de résultats final. Cela signifie que les entrées d'index qui ne satisfont pas le filtre salary sont toujours 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 lues.
Pour en savoir plus, consultez la page des tarifs.
Limites
Outre les 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. - Cloud 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 à exécuter.
Étape suivante
- Découvrez comment optimiser vos requêtes.
- Découvrez comment effectuer des requêtes simples et composées.
- Découvrez comment Cloud Firestore utilise les index.