Abfrage mit Bereichs- und Ungleichheitsfiltern für mehrere Felder – Übersicht
Firestore unterstützt die Verwendung von Bereichs- und Ungleichheitsfiltern für mehrere Felder in einer einzelnen Abfrage. Sie können jetzt Bereichs- und Ungleichheitsbedingungen für mehrere Felder festlegen und die Anwendungsentwicklung vereinfachen, indem Sie die Implementierung der Nachfilterungslogik an Firestore delegieren.
Bereichs- und Ungleichheitsfilter für mehrere Felder
Die folgende Abfrage gibt mithilfe von Bereichsfiltern nach Alter und Größe alle Nutzer zurück, deren Alter größer als 35 ist und deren Größe zwischen 60 und 70 liegt.
Web Version 9 modular
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 für Android
Query query = db.collection("users")
.whereGreaterThan("age", 35)
.whereGreaterThan("height", 60)
.whereLessThan("height", 70);
Kotlin+KTX für 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)
Hinweise zur Indexierung
Bevor Sie mit dem Ausführen von Abfragen beginnen, sollten Sie die Informationen zu Abfragen und zum Firestore-Datenmodell lesen.
In Firestore bestimmt die ORDER BY
-Klausel einer Abfrage, welche Indexe zur Bereitstellung 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.
Um Leistung und Kosten von Firestore-Abfragen zu optimieren, sollten Sie die Reihenfolge der Felder im Index optimieren. Dazu müssen Sie darauf achten, dass der Index von links nach rechts geordnet ist, sodass die Abfrage zu einem Dataset führt, das das Scannen überflüssiger Indexeinträge verhindert.
Angenommen, Sie möchten eine Gruppe von Mitarbeitern durchsuchen und Mitarbeiter finden, deren Gehalt mehr als 100.000 und deren Berufserfahrung größer als 0 ist. Aufgrund Ihres Verständniss des Datasets wissen Sie, dass die Gehaltsbeschränkung selektiver als die Erfahrungsbeschränkung ist. Der ideale Index, der die Anzahl der Indexscans reduzieren würde, wäre (salary [...], experience [...])
. Die schnelle und kostengünstige Abfrage würde also salary
vor experience
anordnen 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 Optimierung von Indexen
Beachten Sie beim Optimieren von Indexen die folgenden Best Practices.
Sortiere Indexfelder nach Gleichheit, gefolgt vom selektivesten Bereich oder Ungleichheitsfeld
Firestore verwendet die Felder ganz links eines zusammengesetzten Index, um die Gleichheitseinschränkungen und gegebenenfalls die Bereichs- oder Ungleichheitseinschränkung für das erste Feld der orderBy()
-Abfrage zu erfüllen. Diese Einschränkungen können die Anzahl der Indexeinträge reduzieren, die von Firestore gescannt werden. Firestore verwendet die verbleibenden Felder des Index, um andere Bereichs- oder Ungleichheitseinschränkungen der Abfrage zu erfüllen. Diese Einschränkungen verringern nicht die Anzahl der von Firestore gescannten Indexeinträge, sondern filtern nicht übereinstimmende Dokumente heraus, sodass die Anzahl der Dokumente, die an die Clients zurückgegeben werden, reduziert wird.
Weitere Informationen zum Erstellen effizienter Indexe finden Sie unter Die Definition eines perfekten Index.
Felder in absteigender Reihenfolge der Auswahl 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 Auswahl der Abfrageeinschränkung anordnet. 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 Indexreihenfolge auswählen als Felder mit geringerer Selektivität.
Um die Anzahl der Dokumente zu minimieren, die Firestore über das Netzwerk scannt und zurückgibt, sollten Sie Felder immer in absteigender Reihenfolge der Auswahl der Abfrageeinschränkung sortieren. Wenn die Ergebnismenge nicht in der erforderlichen Reihenfolge liegt und die Ergebnismenge erwartungsgemäß klein ist, können Sie eine clientseitige Logik implementieren, um sie entsprechend Ihren Bestellerwartungen neu zu ordnen.
Angenommen, Sie möchten eine Gruppe von Mitarbeitern durchsuchen, um Mitarbeiter mit mehr als 100.000 Gehältern zu finden, und die Ergebnisse nach Erfahrungsjahr des Mitarbeiters sortieren. Wenn Sie davon ausgehen, dass nur eine kleine Anzahl von Mitarbeitern ein Gehalt von mehr als 100.000 hat, ist die effizienteste Methode zum Schreiben der Abfrage so:
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`
Das Hinzufügen einer Sortierung von experience
zur Abfrage führt zwar zu den gleichen Dokumenten und muss die Ergebnisse auf den Clients nicht mehr neu anordnen. Die Abfrage liest jedoch möglicherweise wesentlich mehr überflüssige Indexeinträge als die vorherige Abfrage. Das liegt daran, dass Firestore immer einen Index bevorzugt, dessen Präfix der Indexfelder mit der Order by-Klausel der Abfrage übereinstimmt. Wenn experience
in die Klausel „Order by“ aufgenommen wurde, wählt Firestore den Index (experience [...], salary [...])
zum Berechnen von Abfrageergebnissen aus. Da es keine anderen Einschränkungen für experience
gibt, liest Firestore alle Indexeinträge der Sammlung employees
, bevor der Filter salary
angewendet wird, um den endgültigen Ergebnissatz zu ermitteln. Dies bedeutet, dass Indexeinträge, die den Filter salary
nicht erfüllen, trotzdem gelesen werden, wodurch die Latenz und die Kosten der Abfrage erhöht werden.
Preise
Abfragen mit Bereichs- und Ungleichheitsfiltern für mehrere Felder werden basierend auf den gelesenen Dokumenten und den gelesenen Indexeinträgen abgerechnet.
Ausführliche Informationen finden Sie auf der Preisseite.
Beschränkungen
Abgesehen von den Abfrageeinschränkungen müssen Sie die folgenden Einschränkungen beachten, bevor Sie Abfragen mit Bereichs- und Ungleichheitsfiltern für mehrere Felder verwenden:
- Abfragen mit Bereichs- oder Ungleichheitsfiltern für Dokumentfelder und nur Gleichheitseinschränkungen für den Dokumentschlüssel
(__name__)
werden nicht unterstützt. - Firestore begrenzt die Anzahl der Bereichs- oder Ungleichheitsfelder auf 10. Damit soll verhindert werden, dass die Ausführung von Abfragen zu teuer wird.
Weitere Informationen
- Informationen zum Optimieren von Abfragen
- Weitere Informationen zum Ausführen einfacher und zusammengesetzter Abfragen
- Verwendung von Indexen in Firestore