Abfragen mit Bereichs- und Ungleichheitsfiltern für mehrere Felder – Übersicht
In Firestore können Bereichs- und Ungleichheitsfilter für mehrere Felder in einer einzigen Abfrage verwendet werden. Sie können Bereichs- und Ungleichheitsbedingungen für mehrere Felder verwenden und die Implementierung der Logik nach der Filterung an Firestore delegieren, um die Anwendungsentwicklung zu vereinfachen.
Bereichs- und Ungleichheitsfilter für mehrere Felder
In der folgenden Abfrage werden Bereichsfilter für Bevölkerung und Bevölkerungsdichte verwendet, um alle Städte zurückzugeben, in denen mehr als 1.000.000 Einwohner leben und die Bevölkerungsdichte weniger als 10.000 Einwohner pro Quadratkilometer beträgt.
Webversion 9 (modular)
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));
Einheit
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);
Überlegungen zur Indexierung
Lesen Sie sich die Informationen zu Abfragen und dem Firestore-Datenmodell durch, bevor Sie Ihre Abfragen ausführen.
In Firestore wird mit der ORDER BY
-Klausel einer Abfrage festgelegt, welche Indexe für die Ausführung der Abfrage verwendet werden können. Für eine ORDER BY a ASC, b ASC
-Abfrage ist beispielsweise ein zusammengesetzter Index für die a ASC, b ASC
-Felder erforderlich.
Optimieren Sie die Reihenfolge der Felder im Index, um die Leistung und Kosten von Firestore-Abfragen zu optimieren. Achten Sie dabei darauf, dass der Index von links nach rechts sortiert ist, damit die Abfrage zu einem Datensatz führt, der das Scannen unnötiger Indexeinträge verhindert.
Angenommen, Sie möchten in einer Sammlung von Mitarbeitern nach Mitarbeitern in den USA suchen, deren Gehalt über 100.000 $liegt und deren Berufserfahrung mehr als 0 Jahre beträgt. Aus Ihrer Kenntnis des Datensatzes wissen Sie, dass die Gehaltsbeschränkung selektiver ist als die Erfahrungsbeschränkung. Der ideale Index, der die Anzahl der Indexscans reduziert, wäre der (salary [...], experience [...])
. Eine schnelle und kosteneffiziente Abfrage würde also salary
vor experience
sortieren und so aussehen:
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");
Best Practices für die Indexoptimierung
Beachten Sie beim Optimieren von Indexen die folgenden Best Practices.
Indexfelder nach Gleichheitsbedingungen sortieren, gefolgt vom selektivsten Bereichs- oder Ungleichheitsfeld
Firestore verwendet die Felder links im zusammengesetzten Index, um die Gleichheitsbeschränkungen und gegebenenfalls die Bereichs- oder Ungleichheitsbeschränkung für das erste Feld der orderBy()
-Abfrage zu erfüllen. Durch diese Einschränkungen kann die Anzahl der Indexeinträge, die von Firestore gescannt werden, reduziert werden. Firestore verwendet die verbleibenden Felder des Index, um andere Bereichs- oder Ungleichheitsbeschränkungen der Abfrage zu erfüllen. Durch diese Einschränkungen wird nicht die Anzahl der Indexeinträge reduziert, die von Firestore gescannt werden, sondern nicht übereinstimmende Dokumente werden herausgefiltert, sodass die Anzahl der Dokumente, die an die Clients zurückgegeben werden, reduziert wird.
Weitere Informationen zum Erstellen effizienter Indexe finden Sie unter Indexeigenschaften.
Felder in absteigender Reihenfolge der Selektivität der Abfrageeinschränkung sortieren
Damit Firestore den optimalen Index für Ihre Abfrage auswählt, geben Sie eine orderBy()
-Klausel an, die Felder in absteigender Reihenfolge der Selektivität der Abfrageeinschränkung sortiert. Eine höhere Selektivität entspricht einer kleineren Teilmenge von Dokumenten, während eine niedrigere Selektivität einer größeren Teilmenge von Dokumenten entspricht. Achten Sie darauf, dass Sie Bereichs- oder Ungleichheitsfelder mit höherer Selektivität früher in der Indexsortierung auswählen als Felder mit niedrigerer Selektivität.
Um die Anzahl der Dokumente zu minimieren, die von Firestore über das Netzwerk gescannt und zurückgegeben werden, sollten Sie Felder immer in absteigender Reihenfolge der Selektivität der Abfrageeinschränkung anordnen. Wenn der Ergebnissatz nicht in der erforderlichen Reihenfolge ist und voraussichtlich klein ist, können Sie clientseitige Logik implementieren, um ihn gemäß Ihren Anforderungen neu anzuordnen.
Angenommen, Sie möchten in einer Gruppe von Mitarbeitern nach Mitarbeitern in den USA suchen, deren Gehalt über 100.000 $liegt, und die Ergebnisse nach der Berufserfahrung des Mitarbeiters sortieren. Wenn Sie davon ausgehen,dass nur eine kleine Anzahl von Mitarbeitern ein Gehalt von über 100.000 $hat, ist die folgende Abfrage am effizientesten:
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`
Wenn Sie der Abfrage eine Sortierung nach experience
hinzufügen, erhalten Sie zwar dieselben Dokumente und müssen die Ergebnisse nicht auf den Clients neu sortieren, aber die Abfrage liest möglicherweise viel mehr irrelevante Indexeinträge als die vorherige Abfrage. Das liegt daran, dass Firestore immer einen Index bevorzugt, dessen Indexfeldpräfix mit der Order-by-Klausel der Abfrage übereinstimmt. Wenn experience
der Sortierklausel hinzugefügt wurde, wählt Firestore den Index (experience [...], salary [...])
zum Berechnen der Abfrageergebnisse aus. Da es für experience
keine anderen Einschränkungen gibt, liest Firestore alle Indexeinträge der Sammlung employees
, bevor der Filter salary
angewendet wird, um die endgültige Ergebnismenge zu ermitteln. Das bedeutet, dass Indexeinträge, die den salary
-Filter nicht erfüllen, trotzdem gelesen werden, was die Latenz und die Kosten der Abfrage erhöht.
Preise
Abfragen mit Bereichs- und Ungleichheitsfiltern für mehrere Felder werden basierend auf der Anzahl der gelesenen Dokumente und Indexeinträge abgerechnet.
Weitere Informationen finden Sie auf der Seite Preise.
Beschränkungen
Neben den Einschränkungen für Abfragen gelten auch die folgenden Einschränkungen, wenn Sie Abfragen mit Bereichs- und Ungleichheitsfiltern für mehrere Felder verwenden:
- Abfragen mit Bereichs- oder Ungleichheitsfiltern für Dokumentfelder und nur Gleichheitsbeschränkungen für den Dokumentschlüssel
(__name__)
werden nicht unterstützt. - In Firestore ist die Anzahl der Bereichs- oder Ungleichheitsfelder auf 10 Felder beschränkt. So wird verhindert, dass Abfragen zu teuer werden.
Nächste Schritte
- Weitere Informationen zum Optimieren von Abfragen
- Weitere Informationen zum Ausführen einfacher und zusammengesetzter Abfragen
- Informationen zur Verwendung von Indexen in Firestore