Firestore im Datastore-Modus unterstützt die Verwendung von Bereichs- und Ungleichheitsfiltern für mehrere Attribute in einer einzelnen Abfrage. Sie können jetzt Bereichs- und Ungleichheitsbedingungen für mehrere Attribute festlegen und die Anwendungsentwicklung vereinfachen, indem Sie die Implementierung der Nachfilterlogik an Firestore im Datastore-Modus delegieren.
Bereichs- und Ungleichheitsfilter für mehrere Attribute
Die folgende Abfrage gibt alle Nutzer zurück, deren Alter größer als 35 und deren Größe zwischen 60 und 70 liegt. Dazu werden Bereichsfilter für Alter und Größe verwendet.
GQL
SELECT * FROM /users WHERE age > 35 AND height > 60 AND height < 70;
Java
Query<Entity> query =
Query.newEntityQueryBuilder()
.setKind("users")
.setFilter(
CompositeFilter.and(
PropertyFilter.gt("age", 35), PropertyFilter.gt("height", 60), PropertyFilter.lt("height", 70)))
.build();
Hinweise zur Indexierung
Lesen Sie die Informationen über Abfragen, bevor Sie mit dem Ausführen von Abfragen beginnen.
Wenn keine ORDER BY
-Klausel angegeben ist, verwendet Firestore im Datastore-Modus einen beliebigen Index, der die Filterbedingung der Abfrage zur Bereitstellung der Abfrage erfüllen kann. Dadurch wird eine Ergebnismenge erzeugt, die gemäß der Indexdefinition geordnet ist.
Zur Optimierung der Leistung und Kosten von Firestore-Abfragen im Datastore-Modus sollten Sie die Reihenfolge der Attribute im Index optimieren. Dazu müssen Sie dafür sorgen, dass der Index von links nach rechts so geordnet ist, dass die Abfrage in ein Dataset umgewandelt wird, das das Scannen irrelevanter Indexeinträge verhindert.
Angenommen, Sie möchten eine Sammlung von Mitarbeitern durchsuchen und Mitarbeiter finden, deren Gehalt mehr als 100.000 beträgt und deren Berufserfahrung größer als 0 ist. Nach Ihrem Verständnis des Datasets wissen Sie, dass die Gehaltsbeschränkung selektiver ist als die Erfahrungsbeschränkung. Der ideale Index, bei dem die Anzahl der Indexscans reduziert werden würde, ist der Index (salary [...], experience [...])
. Somit würde die schnelle und kostengünstige Abfrage salary
vor experience
bestellen und so aussehen:
GQL
SELECT *
FROM /employees
WHERE salary > 100000 AND experience > 0
ORDER BY salary, experience
Java
Query<Entity> query =
Query.newEntityQueryBuilder()
.setKind("employees")
.setFilter(
CompositeFilter.and(
PropertyFilter.gt("salary", 100000), PropertyFilter.gt("experience", 0)))
.setOrderBy(OrderBy("salary"), OrderBy("experience"))
.build();
Node.js
const query = datastore
.createQuery("employees")
.filter(
and([
new PropertyFilter("salary", ">", 100000),
new PropertyFilter("experience", ">", 0),
])
)
.order("salary")
.order("experience");
Python
query = client.query(kind="employees")
query.add_filter("salary", ">", 100000)
query.add_filter("experience", ">", 0)
query.order = ["-salary", "-experience"]
Best Practices zum Optimieren von Indexen
Beachten Sie beim Optimieren von Indexen die folgenden Best Practices.
Sortieren Sie Abfragen nach Gleichheit, gefolgt vom selektiven Bereich oder Ungleichheitsfeld.
Firestore im Datastore-Modus verwendet die Attribute eines zusammengesetzten Index ganz links, um die Gleichheitseinschränkungen sowie gegebenenfalls die Bereichs- und Ungleichheitseinschränkung für das erste Feld der orderBy()
-Abfrage zu erfüllen. Diese Einschränkungen können die Anzahl der Indexeinträge verringern, die Firestore im Datastore-Modus scannt. Firestore im Datastore-Modus verwendet die verbleibenden Attribute des Index, um andere Bereichs- und Ungleichheitseinschränkungen der Abfrage zu erfüllen. Diese Einschränkungen reduzieren nicht die Anzahl der Indexeinträge, die Firestore im Datastore-Modus scannt, sondern filtert nicht übereinstimmende Entitäten heraus, sodass die Anzahl der Entitäten, die an die Clients zurückgegeben werden, reduziert wird.
Weitere Informationen zum Erstellen effizienter Indexe finden Sie unter Indexstruktur und -definition und Indexe optimieren.
Attribute in absteigender Reihenfolge der Selektivität der Abfrageeinschränkung sortieren
Damit Firestore im Datastore-Modus den optimalen Index für die Abfrage auswählt, geben Sie eine orderBy()
-Klausel an, die Bereichs- und Ungleichheitsattribute in absteigender Reihenfolge der Selektivität der Abfrageeinschränkung sortiert. Eine höhere Selektivität entspricht einer kleineren Teilmenge von Entitäten, während eine niedrigere Selektivität einer größeren Teilmenge von Entitäten entspricht. Achten Sie darauf, dass Sie Bereichs- und Ungleichheitsattribute mit höherer Selektivität früher in der Indexreihenfolge auswählen als Attribute mit niedriger Selektivität.
Um die Anzahl der Entitäten zu minimieren, die Firestore im Datastore-Modus scannt und über das Netzwerk zurückgibt, sollten Sie Attribute immer in absteigender Reihenfolge der Selektivität der Abfrageeinschränkung sortieren. Wenn die Ergebnismenge nicht in der erforderlichen Reihenfolge vorliegt und die Ergebnismenge voraussichtlich klein ist, können Sie clientseitige Logik implementieren, um sie entsprechend Ihren Erwartungen in Bezug auf die Reihenfolge neu anzuordnen.
Angenommen, Sie möchten in einer Sammlung von Mitarbeitenden nach Mitarbeitenden mit einem Gehalt von mehr als 100.000 suchen und die Ergebnisse nach dem Jahr der Erfahrung des Mitarbeiters sortieren. Wenn Sie davon ausgehen, dass nur eine geringe Anzahl von Mitarbeitenden ein Gehalt von mehr als 100.000 Mitarbeitern haben wird, können Sie die Abfrage so am effizientesten schreiben:
Java
Query<Entity> query =
Query.newEntityQueryBuilder()
.setKind("employees")
.setFilter(PropertyFilter.gt("salary", 100000))
.setOrderBy(OrderBy("salary"))
.build();
QueryResults<Entity> results = datastore.run(query);
// Order results by `experience`
Node.js
const query = datastore
.createQuery("employees")
.filter(new PropertyFilter("salary", ">", 100000))
.order("salary");
const [entities] = await datastore.runQuery(query);
// Order results by `experience`
Python
query = client.query(kind="employees")
query.add_filter("salary", ">", 100000)
query.order = ["salary"]
results = query.fetch()
// Order results by `experience`
Während das Hinzufügen einer Sortierung nach experience
zur Abfrage den gleichen Satz von Entitäten ergibt und die Neuanordnung der Ergebnisse auf den Clients vermieden wird, kann die Abfrage viel mehr irrelevante Indexeinträge lesen als die vorherige Abfrage. Das liegt daran, dass Firestore im Datastore-Modus immer einen Index bevorzugt, dessen Indexattribute-Präfix der Reihenfolge nach Klausel der Abfrage entsprechen. Wenn experience
zur Klausel „order by“ hinzugefügt wurde, wählt Firestore im Datastore-Modus den Index (experience [...], salary [...])
zur Berechnung der Abfrageergebnisse aus. Da es für experience
keine anderen Einschränkungen gibt, liest Firestore im Datastore-Modus alle Indexeinträge der Sammlung employees
, bevor der Filter salary
angewendet wird, um den endgültigen Ergebnissatz zu finden. Das bedeutet, dass Indexeinträge, die den Filter salary
nicht erfüllen, dennoch gelesen werden, wodurch sich die Latenz und die Kosten der Abfrage erhöhen.
Preise
Abfragen mit Bereichs- und Ungleichheitsfiltern für mehrere Attribute werden auf Basis der gelesenen Entitäten und Indexeinträge abgerechnet.
Ausführliche Informationen finden Sie in der Preisübersicht.
Beschränkungen
Beachten Sie neben den Abfrageeinschränkungen die folgenden Einschränkungen, bevor Sie Abfragen mit Bereichs- und Ungleichheitsfiltern für mehrere Attribute verwenden:
- Firestore im Datastore-Modus begrenzt die Anzahl der Bereichs- oder Ungleichheitsoperatoren auf 10. Dies soll verhindern, dass Abfragen zu teuer für die Ausführung werden.
Weitere Informationen
- Weitere Informationen zum Optimieren von Abfragen
- Weitere Informationen zum Ausführen einfacher und zusammengesetzter Abfragen
- Hier erfahren Sie, wie Firestore im Datastore-Modus Indexe verwendet.