Übersicht: Abfrage mit Bereichs- und Ungleichheitsfiltern für mehrere Felder

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 festlegen und Ihre indem Sie die Implementierung der Nachfilterungslogik an Firestore

Bereichs- und Ungleichheitsfilter für mehrere Felder

Bei der folgenden Abfrage werden Bereichsfilter für Grundgesamtheit und Dichte verwendet, um alle Städte mit mehr als 1.000.000 Einwohnern und Bevölkerungsdichten weniger als 10.000 Personen pro Flächeneinheit.

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 für 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

$collection = $db->collection('samples/php/cities');
$chainedQuery = $collection
    ->where('population', '>', 1000000)
    ->where('density', '<', 10000);

C#

CollectionReference citiesRef = db.Collection("cities");
Query query = citiesRef
    .WhereGreaterThan("Population", 1000000)
    .WhereLessThan("Density", 10000);
QuerySnapshot querySnapshot = await query.GetSnapshotAsync();
foreach (DocumentSnapshot documentSnapshot in querySnapshot)
{
    var name = documentSnapshot.GetValue<string>("Name");
    var population = documentSnapshot.GetValue<int>("Population");
    var density = documentSnapshot.GetValue<int>("Density");
    Console.WriteLine($"City '{name}' returned by query. Population={population}; Density={density}");
}

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 zum 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. Beispiel: Eine ORDER BY a ASC, b ASC-Abfrage erfordert einen zusammengesetzten Index für die a ASC, b ASC-Felder.

Um die Leistung und Kosten von Firestore-Abfragen zu optimieren, um die Reihenfolge der Felder im Index 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. Das ideale der die Anzahl der Indexscans reduzieren würde, wäre der (salary [...], experience [...]) Eine schnelle und kosteneffiziente Abfrage würde salary also 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 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. Diese Einschränkungen können die Anzahl der Einträge, die Firestore scannt. Firestore verwendet die verbleibenden Felder des Index, um andere Bereichs- oder Ungleichheitsbeschränkungen der Abfrage zu erfüllen. Diese Einschränkungen verringern nicht die Anzahl der Indexeinträge, die von Firestore gescannt werden Sie filtern nicht übereinstimmende Dokumente heraus, sodass die Anzahl der Dokumente, zurückgegeben werden.

Weitere Informationen zum Erstellen effizienter Indexe finden Sie unter Indexeigenschaften.

Felder in absteigender Reihenfolge der Auswahl der Abfrageeinschränkung sortieren

Damit Firestore den optimalen Index für Ihre Abfrage auswählt, Sie geben eine orderBy()-Klausel an, die Felder in absteigender Reihenfolge der Abfrage anordnet zur Auswahl der Einschränkungsselektivität. 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 die Ergebnismenge nicht in der erforderlichen Reihenfolge liegt und der erwartet wird, dass die Ergebnismenge klein ist, können Sie clientseitige Logik implementieren, und bestell ihn entsprechend deinen Erwartungen neu.

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 Berufsjahren sortieren. Wenn Sie davon ausgehen, dass nur eine kleine Anzahl von Mitarbeitenden Gehälter hat größer als 100.000 $ist, lässt sich die Abfrage so am effizientesten 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 experience-Reihenfolge hinzufügen, erhalten Sie den gleichen Satz. und eine Neuanordnung der Ergebnisse bei der Kundschaft vermeidet, kann die Abfrage viel mehr irrelevante Indexeinträge lesen 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 keine anderen Einschränkungen experience, wird Firestore alle Indexeinträge der employees aus, bevor Sie den Filter salary anwenden, um das endgültige Ergebnismenge. Das bedeutet, dass Indexeinträge, die die salary nicht erfüllen, Filter immer noch gelesen, wodurch sich die Latenz und die Kosten der Abfrage erhöhen.

Preise

Abfragen mit Bereichs- und Ungleichheitsfiltern für mehrere Felder werden basierend auf gelesene Dokumente und gelesene Indexeinträge.

Weitere Informationen finden Sie auf der Seite Preise.

Beschränkungen

Abgesehen von den Abfrageeinschränkungen müssen Sie folgende Einschränkungen beachten, 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.
  • Firestore begrenzt die Anzahl der Bereichs- oder Ungleichheitsfelder auf 10. Damit soll verhindert werden, dass Abfragen zu teuer werden. ausgeführt werden soll.

Nächste Schritte