Abfrage mit Bereichs- und Ungleichheitsfiltern für mehrere Properties

Firestore im Datastore-Modus unterstützt die Verwendung von Bereichs- und Ungleichheitsfiltern für mehrere Properties in einer einzelnen Abfrage. Mit dieser Funktion können Sie Bereichs- und Ungleichheitsbedingungen für mehrere Properties festlegen. Außerdem wird die Anwendungsentwicklung vereinfacht, da die Implementierung der Logik für die Nachfilterung an Firestore im Datastore-Modus delegiert wird.

Bereichs- und Ungleichheitsfilter für mehrere Properties

In der folgenden Abfrage werden Bereichsfilter für Priorität und Tage verwendet, um alle Aufgaben mit einer Priorität von über vier und einer verbleibenden Bearbeitungszeit von weniger als drei Tagen zurückzugeben.

Go

query := datastore.NewQuery("Task").
   FilterField("priority", ">", 4).
   FilterField("days", "<", 3).

GQL

SELECT * FROM /tasks WHERE priority > 4 AND days < 3;

Java

Query<Entity> query =
    Query.newEntityQueryBuilder()
      .setKind("Task")
      .setFilter(
        CompositeFilter.and(
            PropertyFilter.gt("priority", 4), PropertyFilter.lt("days", 3)))
    .build();

Node.js

const query = datastore
  .createQuery('Task')
  .filter(
    and([
      new PropertyFilter('priority', '>', 4),
      new PropertyFilter('days', '<', 3),
    ])
  );

Python

from google.cloud import datastore
client = datastore.Client()
query = client.query(kind="Task")
query.add_filter(filter=PropertyFilter("priority", ">", 4))
query.add_filter(filter=PropertyFilter("days", "<", 3))

PHP

$query = $datastore->query()
    ->kind('Task')
    ->filter('priority', '>', 4)
    ->filter('days', '<', 3)

C#

Query query = new Query("Task")
{
  Filter = Filter.And(Filter.GreaterThan("priority", 4),
    Filter.LessThan("days", 3))
};

Ruby

query = datastore.query("Task")
                 .where("priority", ">", 4)
                 .where("days", "<", 3)

Überlegungen zur Indexierung

Bevor Sie Abfragen ausführen, sollten Sie sich über Abfragen informieren.

Wenn keine ORDER BY-Klausel angegeben ist, verwendet Firestore im Datastore-Modus jeden Index, der die Filterbedingung der Abfrage erfüllen kann, um die Abfrage zu bedienen. Bei diesem Ansatz wird ein Ergebnissatz generiert, der gemäß der Indexdefinition sortiert ist.

Um die Leistung und Kosten von Abfragen in Firestore im Datastore-Modus zu optimieren, sollten Sie die Reihenfolge der Properties im Index optimieren. Achten Sie dazu darauf, dass Ihr Index von links nach rechts sortiert ist, damit die Abfrage in einen Datensatz umgewandelt wird, der das Scannen überflüssiger 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 der Datasets wissen Sie, dass die Gehaltsbeschränkung selektiver ist als die Erfahrungsbeschränkung. Ein Index, der die Anzahl der Indexscans reduziert, ist der (salary [...], experience [...])-Index. Daher wird bei einer schnellen und kosteneffizienten Abfrage salary vor experience sortiert, wie im folgenden Beispiel gezeigt:

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

Beachten Sie beim Optimieren von Indexen die folgenden Best Practices.

Abfragen nach Gleichheitsbedingungen sortieren, gefolgt vom selektivsten Bereich oder Ungleichheitsfeld

Firestore im Datastore-Modus verwendet die am weitesten links stehenden Eigenschaften eines zusammengesetzten Index, um die Gleichheitsbeschränkungen und gegebenenfalls die Bereichs- und Ungleichungsbeschränkungen für das erste Feld der orderBy()-Abfrage zu erfüllen. Diese Einschränkungen können die Anzahl der Indexeinträge verringern, die in Firestore im Datastore-Modus gescannt werden. Firestore im Datastore-Modus verwendet die verbleibenden Eigenschaften des Index, um andere Bereichs- und Ungleichheitsbeschränkungen der Abfrage zu erfüllen. Durch diese Einschränkungen wird nicht die Anzahl der Indexeinträge reduziert, die von Firestore im Datastore-Modus gescannt werden. Es werden jedoch nicht übereinstimmende Entitäten herausgefiltert, sodass die Anzahl der an die Clients zurückgegebenen Entitäten verringert wird.

Weitere Informationen zum Erstellen effizienter Indexe finden Sie unter Indexstruktur und ‑definition und Indexe optimieren.

Eigenschaften in absteigender Reihenfolge der Selektivität der Abfrageeinschränkung sortieren

Damit Firestore im Datastore-Modus den optimalen Index für Ihre Abfrage auswählt, geben Sie eine orderBy()-Klausel an, die Bereichs- und Ungleichheitseigenschaften anhand der Selektivität ihrer Einschränkungen in Ihrer Abfrage sortiert, beginnend mit der selektivsten. Bei einer höheren Selektivität werden weniger Entitäten abgeglichen, bei einer niedrigeren Selektivität mehr. Ordnen Sie in der Indexreihenfolge Bereichs- und Ungleichheitseigenschaften mit höherer Selektivität vor Eigenschaften mit niedrigerer Selektivität ein.

Um die Anzahl der Entitäten zu minimieren, die in Firestore im Datastore-Modus gescannt und über das Netzwerk zurückgegeben werden, sollten Sie Eigenschaften immer in absteigender Reihenfolge der Selektivität der Abfrageeinschränkung sortieren. Wenn der Ergebnissatz nicht in der erforderlichen Reihenfolge ist und voraussichtlich klein ist, können Sie clientseitige Logik implementieren, um ihn gemäß Ihren Anforderungen neu anzuordnen.

Angenommen, Sie möchten in einer Mitarbeiterdatenbank nach Mitarbeitern in den USA suchen, deren Gehalt über 100.000 $liegt, und die Ergebnisse nach der Berufserfahrung der Mitarbeiter sortieren. Wenn Sie davon ausgehen,dass nur eine kleine Anzahl von Mitarbeitern ein Gehalt von über 100.000 $hat, können Sie die Abfrage so effizient formulieren:

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`

Wenn Sie der Abfrage eine Sortierung nach experience hinzufügen, werden zwar dieselben Entitäten zurückgegeben und die Ergebnisse müssen nicht auf den Clients neu sortiert werden, aber die Abfrage liest möglicherweise viel mehr überflüssige Indexeinträge als die vorherige Abfrage. Das liegt daran, dass in Firestore im Datastore-Modus immer ein Index bevorzugt wird, dessen Indexeigenschaften mit dem Präfix der Order-by-Klausel der Abfrage übereinstimmen. Wenn experience der ORDER BY-Klausel hinzugefügt wurde, wird in Firestore im Datastore-Modus der Index (experience [...], salary [...]) zum Berechnen der Abfrageergebnisse ausgewählt. Da es keine anderen Einschränkungen für experience gibt, werden in Firestore im Datastore-Modus alle Indexeinträge der Sammlung employees gelesen, bevor der salary-Filter angewendet wird, um die endgültige Ergebnismenge zu ermitteln. 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 Properties werden basierend auf den gelesenen Entitäten und Indexeinträgen abgerechnet.

Weitere Informationen finden Sie auf der Seite Preise.

Beschränkungen

Neben den Einschränkungen für Abfragen gelten auch die folgenden Einschränkungen, wenn Sie Abfragen mit Bereichs- und Ungleichheitsfiltern für mehrere Properties verwenden:

  • Damit Abfragen nicht zu teuer werden, ist die Anzahl der Intervall- oder Ungleichheitsoperatoren in Firestore im Datastore-Modus auf 10 beschränkt.

Weitere Informationen