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