Cloud Firestore unterstützt die Verwendung von Bereichs- und Ungleichheitsfiltern für mehrere Felder in einer einzelnen Abfrage. Sie können Bereichs- und Ungleichheitsbedingungen für mehrere Felder festlegen und die Anwendungsentwicklung vereinfachen, indem Sie die Implementierung der Logik für die Nachfilterung an Cloud Firestore delegieren.
Bereichs- und Ungleichheitsfilter für mehrere Felder
In der folgenden Abfrage werden Bereichsfilter für die Bevölkerung und die Dichte verwendet, um alle Städte zurückzugeben, in denen die Bevölkerung mehr als 1.000.000 Einwohner beträgt und die Bevölkerungsdichte weniger als 10.000 Einwohner pro Flächeneinheit 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
Bevor Sie Ihre Abfragen ausführen, sollten Sie sich über [Abfragen][1] und das Cloud Firestore-[Datenmodell][2] informieren.
In Cloud 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.
Wenn Sie die Leistung und die Kosten von Cloud Firestore-Abfragen optimieren möchten, optimieren Sie die Reihenfolge der Felder im Index. Achten Sie dazu darauf, dass Ihr Index von links nach rechts sortiert ist, sodass die Abfrage auf ein Dataset reduziert wird, das das Scannen unnötiger Indexeinträge verhindert.
Angenommen, Sie möchten eine Sammlung von Mitarbeitern durchsuchen und Mitarbeiter in den USA finden, deren Gehalt mehr als 100.000 $ beträgt und die mehr als 0 Jahre Berufserfahrung haben. Aufgrund Ihres Verständnisses des Datasets wissen Sie, dass die Gehaltsbeschränkung selektiver ist als die Erfahrungsbeschränkung. Der ideale Index, der die Anzahl der Indexscans reduzieren würde, wäre (salary [...], experience [...]). Eine schnelle und kostengünstige 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 Optimierung von Indexen
Beachten Sie beim Optimieren von Indexen die folgenden Best Practices.
Indexfelder nach Gleichheiten sortieren, gefolgt vom selektivsten Bereichs- oder Ungleichheitsfeld
Cloud Firestore verwendet die Felder ganz links eines zusammengesetzten Index, um die Gleichheitsbeschränkungen und die Bereichs- oder Ungleichheitsbeschränkung (falls vorhanden) für das erste Feld der orderBy()-Abfrage zu erfüllen. Diese Einschränkungen können die Anzahl der Indexeinträge reduzieren, die von Cloud Firestore gescannt werden. Cloud Firestore verwendet die verbleibenden Felder des Index, um andere Bereichs- oder Ungleichheitsbeschränkungen der Abfrage zu erfüllen. Diese Einschränkungen reduzieren nicht die Anzahl der Indexeinträge, die Cloud Firestore scannt, sondern filtern nicht übereinstimmende Dokumente heraus, sodass die Anzahl der an die Clients zurückgegebenen Dokumente reduziert wird.
Weitere Informationen zum Erstellen effizienter Indexe finden Sie unter [Indexeigenschaften][4].
Felder in absteigender Reihenfolge der Selektivität der Abfrageeinschränkung sortieren
Damit Cloud 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 in der Indexreihenfolge vor Feldern mit niedrigerer Selektivität auswählen.
Um die Anzahl der Dokumente zu minimieren, die Cloud Firestore scannt und über das Netzwerk zurückgibt, sollten Sie Felder immer in absteigender Reihenfolge der Selektivität der Abfrageeinschränkung sortieren. Wenn die Ergebnismenge nicht in der erforderlichen Reihenfolge ist und die Ergebnismenge voraussichtlich klein ist, können Sie eine clientseitige Logik implementieren, um sie gemäß Ihren Erwartungen neu zu sortieren.
Angenommen, Sie möchten eine Sammlung von Mitarbeitern durchsuchen, um Mitarbeiter in den USA zu finden, deren Gehalt mehr als 100.000 $ beträgt, und die Ergebnisse nach der Berufserfahrung des Mitarbeiters in Jahren sortieren. Wenn Sie davon ausgehen, dass nur wenige Mitarbeiter ein Gehalt von mehr als 100.000 $ haben, ist die effizienteste Methode, die Abfrage so zu schreiben:
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 dieselben Dokumente und müssen die Ergebnisse auf den Clients nicht neu sortieren. Die Abfrage liest jedoch möglicherweise viel mehr irrelevante Indexeinträge als die vorherige Abfrage. Das liegt daran, dass Cloud Firestore immer einen Index bevorzugt, dessen Indexfeldpräfix mit der ORDER BY-Klausel der Abfrage übereinstimmt. Wenn experience zur ORDER BY-Klausel hinzugefügt würde, würde Cloud Firestore den Index (experience [...], salary [...]) für die Berechnung der Abfrageergebnisse auswählen. Da es keine weiteren Einschränkungen für experience gibt, liest Cloud Firestore alle Indexeinträge der Sammlung employees, bevor der Filter salary angewendet wird, um die endgültige Ergebnismenge zu finden. 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 gelesenen Dokumenten und gelesenen Indexeinträgen abgerechnet.
Ausführliche Informationen finden Sie auf der Seite [Preise][5].
Beschränkungen
Beachten Sie neben den [Abfragebeschränkungen][6] die folgenden Einschränkungen, bevor 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. - Cloud Firestore beschränkt die Anzahl der Bereichs- oder Ungleichheitsfelder auf 10. So wird verhindert, dass die Ausführung von Abfragen zu teuer wird.
Nächste Schritte
- [Abfragen optimieren][3]
- Weitere Informationen zum [Ausführen einfacher und zusammengesetzter Abfragen][8].
- Informationen zur Verwendung von Indexen in [Cloud Firestore][9]
[1]: /docs/firestore/query-data/get-data [2]: /docs/firestore/data-model [3]: /docs/firestore/query-data/multiple-range-optimize-indexes [4]: /docs/firestore/concepts/index-overview#index_properties [5]: /docs/firestore/pricing [6]: /docs/firestore/query-data/queries#query_limitations [7]: https://en.wikipedia.org/wiki/Disjunctive_normal_form [8]: /docs/firestore/query-data/queries [9]: /docs/firestore/concepts/index-overview [10]: /docs/firestore/query-data/multiple-range-optimize-indexes