Projektionsabfragen

Hinweis: Entwicklern von neuen Anwendungen wird dringend empfohlen, die NDB-Clientbibliothek zu verwenden. Diese bietet im Vergleich zur vorliegenden Clientbibliothek verschiedene Vorteile, z. B. das automatische Caching von Entitäten über die Memcache API. Wenn Sie derzeit die ältere DB-Clientbibliothek verwenden, finden Sie weitere Informationen im Leitfaden zur Migration von DB- zu NDB-Clientbibliotheken.

Die meisten Datastore-Abfragen geben ganze Entitäten als Ergebnisse zurück, häufig benötigt eine Anwendung jedoch nur einige wenige Attribute einer Entität. Mit Projektionsabfragen können Sie Datastore nur auf die Attribute einer Entität abfragen, die Sie wirklich benötigen, und zwar mit einer geringeren Latenz und niedrigeren Kosten als beim Abrufen der ganzen Entität.

Projektionsabfragen ähneln SQL-Abfragen der folgenden Form:

SELECT name, email, phone FROM CUSTOMER

Sie können alle Filter- und Sortierfunktionen, die für Standardentitätsabfragen verfügbar sind, innerhalb der unten beschriebenen Einschränkungen verwenden. Die Abfrage gibt gekürzte Ergebnisse zurück, wobei nur die angegebenen Attribute (im Beispiel name, email und phone) mit Werten gefüllt sind. Alle anderen Attribute enthalten keine Daten.

Projektionsabfragen in Python 2 verwenden

Sie geben eine Projektion so an: Projektionsabfragen werden sowohl von Query-Objekten als auch von GqlQuery-Objekten unterstützt. Beide Klassen benötigen diesen Import:

from google.appengine.ext import db

Sie geben eine Projektion auf folgende Weise an:

proj = db.Query(entity_name, projection=('property_1', 'property_2','property_n'))

proj = db.GqlQuery("SELECT property_1, property_2, property_n FROM entity_name")

Sie verarbeiten die Ergebnisse dieser Abfragen genauso wie bei einer Standardentitätsabfrage, z. B., durch Iteration über die Ergebnisse.

Im folgenden Beispiel werden die Attribute title, read_path und date_written aller EventLog-Einträge abgefragt und in aufsteigender Reihenfolge nach date_written sortiert. Der Wert jedes Attributs wird ins Anwendungslog geschrieben:

for proj in db.GqlQuery("SELECT title, read_path, date_written" +
                        "FROM EventLog" +
                        "ORDER BY date_written ASC"):
  logging.info(proj.title)
  logging.info(proj.read_path)
  logging.info(proj.date_written)

Gruppierung(experimentell)

Projektionsabfragen können mit dem Suchbegriff distinct dafür sorgen, dass wirklich nur ein einziges Mal vorkommende Ergebnisse zurückgegeben werden. So wird nur das erste Ergebnis für Entitäten zurückgegeben, die für die projizierten Attribute dieselben Werte haben.

query = db.Query(projection=['A', 'B'], distinct=True).filter('B >', 1).order('-B, A')

Einschränkungen bei Projektionen

Projektionsabfragen unterliegen folgenden Einschränkungen:

  • Nur indexierte Attribute können projiziert werden.

    Projektion wird für Properties, die nicht explizit oder implizit indexiert sind, nicht unterstützt. Lange Textstrings (Text) und lange Bytestrings (Blob) werden nicht indexiert.

  • Ein Attribut kann nicht mehr als einmal projiziert werden.

  • Attribute, auf die in einem Gleichheitsfilter (=) oder Zugehörigkeitsfilter (IN) verwiesen wird, können nicht projiziert werden.

    Beispiel:

    SELECT A FROM kind WHERE B = 1
    

    ist gültig (projiziertes Attribut nicht im Gleichheitsfilter verwendet), wie auch

    SELECT A FROM kind WHERE A > 1
    

    (kein Gleichheitsfilter), aber

    SELECT A FROM kind WHERE A = 1
    

    (projiziertes Attribut in Gleichheitsfilter verwendet) ist nicht gültig.

  • Von einer Projektionsabfrage zurückgegebene Ergebnisse können nicht wieder in Datastore gespeichert werden.

    Da die Abfrage Ergebnisse zurückgibt, die nur teilweise ausgefüllt sind, können diese Ergebnisse nicht wieder in Datastore geschrieben werden.

Projektionen und mehrwertige Attribute

Bei der Projektion eines Attributs mit mehreren Werten werden nicht alle Werte dieses Attributs ausgefüllt. Stattdessen wird eine separate Entität für jede nur einmal vorkommende Kombination von projizierten Werten zurückgegeben, die mit der Abfrage übereinstimmen. Angenommen, Sie haben eine Entität vom Typ Foo mit den beiden mehrwertigen Attributen A und B:

entity = Foo(A=[1, 1, 2, 3], B=['x', 'y', 'x'])

dann gibt die Projektionsabfrage

SELECT A, B FROM Foo WHERE A < 3

vier Entitäten mit den folgenden Wertekombinationen zurück:

A = 1, B = 'x'
A = 1, B = 'y'
A = 2, B = 'x'
A = 2, B = 'y'

Bei einer Entität mit einem mehrwertigen Attribut ohne Werte werden keine Einträge in den Index aufgenommen und keine Ergebnisse für diese Entität von einer Projektionsabfrage mit diesem Attribut zurückgegeben.

Indexe für Projektionen

Bei Projektionsabfragen müssen alle in der Projektion angegebenen Attribute in einem Datastore-Index enthalten sein. Der App Engine-Entwicklungsserver generiert automatisch die benötigten Indexe in der Indexkonfigurationsdatei index.yaml, die mit Ihrer Anwendung hochgeladen wird.

Die Anzahl der benötigten Indexe können Sie beispielsweise durch konstantes Projizieren derselben Attribute reduzieren, auch wenn nicht immer alle benötigt werden. Diese Abfragen benötigen beispielsweise zwei getrennte Indexe:

SELECT A, B FROM Kind
SELECT A, B, C FROM Kind

Wenn Sie immer die Attribute A, B und C projizieren, auch wenn C nicht benötigt wird, ist nur ein Index erforderlich.

Wenn Sie eine bestehende Abfrage in eine Projektionsabfrage umwandeln, müssen Sie gegebenenfalls einen neuen Index erstellen, wenn die Attribute für die Projektion nicht bereits in einem anderen Teil der Abfrage enthalten sind. Angenommen, Sie haben diese bestehende Abfrage:

SELECT * FROM Kind WHERE A > 1 ORDER BY A, B

Sie benötigt diesen Index:

Index(Kind, A, B)

Wenn diese in eine dieser Projektionsabfragen konvertiert wird:

SELECT C FROM Kind WHERE A > 1 ORDER BY A, B
SELECT A, B, C FROM Kind WHERE A > 1 ORDER BY A, B

wird ein neues Attribut (C) eingeführt. Dies erfordert die Erstellung eines neuen Indexes Index(Kind, A, B, C). Die Projektionsabfrage

SELECT A, B FROM Kind WHERE A > 1 ORDER BY A, B

ändert den erforderlichen Index nicht, da die projizierten Attribute A und B bereits in der vorhandenen Abfrage enthalten sind.