Hinweis: Entwicklern neuer Anwendungen wird dringend empfohlen, die NDB-Clientbibliothek zu verwenden. Sie bietet im Vergleich zu dieser Clientbibliothek mehrere Vorteile, beispielsweise das automatische Caching von Entitäten über die Memcache API. Wenn Sie derzeit die ältere DB-Clientbibliothek verwenden, lesen Sie die Anleitung zur Migration von DB zu NDB.
Datenobjekte in Cloud Datastore werden als Entitäten bezeichnet. Eine Entität hat ein oder mehrere benannte Attribute, die jeweils einen oder mehrere Werte enthalten können. Entitäten derselben Art müssen nicht dieselben Attribute haben und die Werte der Entitäten für ein bestimmtes Attribut müssen nicht alle denselben Datentyp haben. Falls erforderlich, kann eine Anwendung derartige Einschränkungen in einem eigenen Datenmodell festlegen und durchsetzen.
Cloud Datastore unterstützt eine Vielzahl von Datentypen für Attributwerte. Diese umfassen unter anderem:
- Ganzzahlen
- Gleitkommazahlen
- Strings
- Datumsangaben
- Binärdaten
Eine vollständige Liste der Typen finden Sie unter Attribute und Werttypen.
Jede Entität in Cloud Datastore verfügt über einen Schlüssel, der sie eindeutig identifiziert. Der Schlüssel besteht aus den folgenden Komponenten:
- Namespace der Entität, der die Mehrinstanzenfähigkeit ermöglicht
- Art der Entität, mit der sie für Cloud Datastore-Abfragen kategorisiert wird
- Kennzeichnung für die einzelne Entität, entweder
- ein String mit dem Schlüsselnamen oder
- eine ganzzahlige numerische ID
- Optionaler Ancestor-Pfad zur Entität in der Cloud Datastore-Hierarchie
Eine Anwendung kann eine einzelne Entität mithilfe des Entitätsschlüssels aus Cloud Datastore abrufen oder eine bzw. mehrere Entitäten mit einer Abfrage anhand der Schlüssel oder Attributwerte der Entitäten ermitteln.
Das Python App Engine SDK enthält eine Datenmodellierungsbibliothek zur Darstellung von Cloud Datastore-Entitäten als Instanzen von Python-Klassen sowie zum Speichern und Abrufen dieser Instanzen in Cloud Datastore.
Cloud Datastore selbst erzwingt keine Einschränkungen für die Struktur von Entitäten, beispielsweise ob ein bestimmtes Attribut einen Wert eines bestimmten Typs hat. Diese Aufgabe bleibt der Anwendung und der Datenmodellierungsbibliothek überlassen.
Arten und Kennungen
Jede Cloud Datastore-Entität ist von einer bestimmten Art. Diese kategorisiert die Entität für Abfragen. In einer Personalanwendung kann beispielsweise jeder Mitarbeiter eines Unternehmens mit einer Entität der Art Employee
dargestellt werden. In der Python Datastore API wird die Art einer Entität durch ihre Modellklasse bestimmt, die Sie in Ihrer Anwendung als abgeleitete Klasse der Klasse db.Model
der Datenmodellierungsbibliothek festlegen. Der Name der Modellklasse wird zur Art der zugehörigen Entitäten. Alle Artnamen, die mit zwei Unterstrichen (__
) beginnen, sind reserviert und dürfen nicht verwendet werden.
Im folgenden Beispiel wird eine Entität der Art Employee
erstellt. Außerdem werden ihre Attributwerte angegeben und die Entität wird in Datastore gespeichert:
import datetime
from google.appengine.ext import db
class Employee(db.Model):
first_name = db.StringProperty()
last_name = db.StringProperty()
hire_date = db.DateProperty()
attended_hr_training = db.BooleanProperty()
employee = Employee(first_name='Antonio',
last_name='Salieri')
employee.hire_date = datetime.datetime.now().date()
employee.attended_hr_training = True
employee.put()
Die Klasse Employee
deklariert vier Attribute für das Datenmodell: first_name
, last_name
, hire_date
und attended_hr_training
. Die Basisklasse Model
gewährleistet, dass die Attribute von Employee
-Objekten diesem Modell entsprechen. Beispielsweise würde die Zuweisung eines Stringwerts zum Attribut hire_date
zu einem Laufzeitfehler führen, da das Datenmodell für hire_date
als db.DateProperty
deklariert wurde.
Neben der Art verfügt jede Entität über eine Kennung, die beim Erstellen der Entität zugewiesen wird. Weil sie Teil des Schlüssels der Entität ist, ist die Kennung dauerhaft mit der Entität verknüpft und kann nicht geändert werden. Es gibt zwei Möglichkeiten der Zuweisung:
- Die Anwendung kann ihren eigenen Schlüsselnamen als String für die Entität angeben.
- Cloud Datastore kann der Entität automatisch eine ganzzahlige numerische ID zuweisen.
Zum Zuweisen eines Schlüsselnamens zu einer Entität übergeben Sie beim Erstellen der Entität das benannte Argument key_name
an den Modellklassenkonstruktor:
# Create an entity with the key Employee:'asalieri'.
employee = Employee(key_name='asalieri')
Wenn Cloud Datastore automatisch eine numerische ID zuweisen soll, lassen Sie das Argument key_name
weg:
# Create an entity with a key such as Employee:8261.
employee = Employee()
Kennungen zuweisen
Wenn Sie Cloud Datastore automatisch IDs zuweisen lassen, haben Sie die Wahl zwischen zwei verschiedenen Richtlinien für automatische IDs:
- Die Richtlinie
default
generiert eine zufällige Abfolge von bisher nicht verwendeten IDs, die näherungsweise gleichmäßig verteilt sind. Jede ID kann maximal 16 Dezimalstellen enthalten. - Die Richtlinie
legacy
erstellt eine Abfolge nicht aufeinanderfolgender IDs aus kleineren Ganzzahlen.
Wenn Sie die Entitäts-IDs für den Nutzer anzeigen möchten und/oder deren Reihenfolge wichtig ist, ist eine manuelle Zuordnung die beste Lösung.
Cloud Datastore generiert eine zufällige Abfolge von bisher nicht verwendeten IDs, die näherungsweise gleichmäßig verteilt sind. Jede ID kann maximal 16 Dezimalstellen enthalten.
Vom System zugeordnete ID-Werte sind für die Entitätengruppe garantiert eindeutig. Wenn Sie eine Entität aus einer Entitätengruppe oder einem Namespace in eine andere Entitätengruppe oder einen anderen Namespace kopieren und den ID-Teil des Schlüssels beibehalten möchten, achten Sie darauf, dass Sie die ID zuerst zuordnen, damit Datastore sie nicht für eine zukünftige Zuweisung auswählt.
Ancestor-Pfade
Entitäten in Cloud Datastore sind hierarchisch organisiert, ähnlich der Verzeichnisstruktur eines Dateisystems. Wenn Sie eine Entität erstellen, können Sie optional eine weitere Entität als übergeordnetes Element angeben. Die neue Entität ist dann ein untergeordnetes Element der übergeordneten Entität. Im Gegensatz zu einem Dateisystem muss die übergeordnete Entität nicht tatsächlich vorhanden sein. Eine Entität ohne übergeordnetes Element wird als Stammentität bezeichnet. Die Verknüpfung zwischen einer Entität und ihrer übergeordneten Entität ist dauerhaft und kann nicht geändert werden, nachdem die Entität erstellt wurde. Cloud Datastore weist zwei Entitäten mit derselben übergeordneten Entität oder zwei Stammentitäten (Entitäten ohne übergeordnete Entität) niemals dieselbe numerische ID zu.
Alle übergeordneten Elemente einer Entität werden als ihre Ancestors bezeichnet und alle untergeordneten Entitäten sind ihre Nachfolger. Eine Stammentität und alle ihre Nachfolger gehören zu derselben Entitätengruppe. Die Abfolge der Entitäten, von einer Stammentität über die untergeordneten Elemente bis zu einer bestimmten Entität, bildet den Ancestor-Pfad. Der vollständige Schlüssel, der die Entität identifiziert, besteht aus einer Abfolge von Art/Kennungs-Paaren, die den Ancestor-Pfad angeben und mit dem Paar der Entität selbst enden:
[Person:GreatGrandpa, Person:Grandpa, Person:Dad, Person:Me]
Bei einer Stammentität ist der Ancestor-Pfad leer und der Schlüssel besteht ausschließlich aus der eigenen Art und der eigenen Kennung der Entität:
[Person:GreatGrandpa]
Dieses Konzept wird anhand des folgenden Diagramms veranschaulicht:
Zur Angabe der übergeordneten Entität einer Entität verwenden Sie beim Erstellen der untergeordneten Entität das Argument parent
für den Modellklassenkonstruktor. Der Wert dieses Arguments kann die übergeordnete Entität selbst oder ihr Schlüssel sein. Der Schlüssel lässt sich durch Aufrufen der Methode key()
der übergeordneten Entität ermitteln. Im folgenden Beispiel wird eine Entität der Art Address
erstellt. Außerdem werden zwei Möglichkeiten zum Angeben einer Entität der Art Employee
als deren übergeordnete Entität gezeigt:
# Create Employee entity
employee = Employee()
employee.put()
# Set Employee as Address entity's parent directly...
address = Address(parent=employee)
# ...or using its key
e_key = employee.key()
address = Address(parent=e_key)
# Save Address entity to datastore
address.put()
Transaktionen und Entitätengruppen
Jeder Vorgang zum Erstellen, Aktualisieren und Löschen einer Entität findet im Rahmen einer Transaktion statt. Eine einzelne Transaktion kann eine beliebige Anzahl solcher Vorgänge umfassen. Zur Wahrung der Datenkonsistenz sorgt die Transaktion dafür, dass alle enthaltenen Vorgänge auf Cloud Datastore als Einheit angewendet werden oder keiner der Vorgänge angewendet wird, falls einer der Vorgänge fehlschlägt. Darüber hinaus greifen alle strikt konsistenten Lesevorgänge (Ancestor-Abfragen oder -Abrufe) innerhalb derselben Transaktion auf einen konsistenten Snapshot der Daten zurück.
Wie oben bereits erwähnt besteht eine Entitätengruppe aus einer Reihe von Entitäten, die über einen Ancestor-Pfad mit einem gemeinsamen Stammelement verbunden sind. Die Anordnung von Daten in Entitätengruppen kann einschränken, welche Transaktionen ausgeführt werden können:
- Alle Daten, auf die eine Transaktion zugreift, müssen in maximal 25 Entitätengruppen enthalten sein.
- Wenn Sie Abfragen innerhalb einer Transaktion verwenden möchten, müssen die Daten so in Entitätengruppen angeordnet werden, dass Sie Ancestor-Filter angeben können, die mit den richtigen Daten übereinstimmen.
- Es gibt einen Schreibdurchsatzgrenzwert von ca. einer Transaktion pro Sekunde innerhalb einer einzelnen Entitätengruppe. Diese Begrenzung ist vorhanden, weil Cloud Datastore eine synchrone Replikation ohne Master jeder Entitätengruppe über einen breiten geografischen Bereich hinweg durchführt, um hohe Verlässlichkeit und Fehlertoleranz zu ermöglichen.
In vielen Anwendungen kann es akzeptabel sein, für den Abruf einer breiten Ansicht nicht zusammengehöriger Daten Eventual Consistency zu verwenden, also eine entitätsgruppenübergreifende Nicht-Ancestor-Abfrage, die gelegentlich etwas veraltete Daten zurückgeben kann. Anschließend wird dann strikte Konsistenz (eine Ancestor-Abfrage oder ein get
einer einzelnen Entität) verwendet, um eine einzelne Gruppe von eng zusammengehörigen Daten anzuzeigen oder zu bearbeiten. In derartigen Anwendungen ist es oft ein guter Ansatz, für jeden Satz eng zusammengehöriger Daten jeweils eine separate Entitätengruppe zu verwenden.
Weitere Informationen finden Sie unter Für strikte Konsistenz strukturieren.
Attribute und Werttypen
Die mit einer Entität verknüpften Datenwerte bestehen aus einem oder mehreren Attributen. Jedes Attribut hat einen Namen und einen oder mehrere Werte. Ein Attribut kann Werte mit mehr als einem Typ haben und zwei Entitäten können Werte unterschiedlichen Typs für dasselbe Attribut haben. Attribute können indexiert oder nicht indexiert sein. Abfragen, die nach einem Attribut A sortieren oder filtern, ignorieren Entitäten, bei denen A nicht indexiert ist. Eine Entität kann höchstens 20.000 indexierte Attribute haben.
Die folgenden Werttypen werden unterstützt:
Werttyp | Python-Typ(en) | Sortierfolge | Hinweise |
---|---|---|---|
Ganzzahl | int long |
Numerisch | 64-Bit-Ganzzahl, signiert |
Gleitkommazahl | float |
Numerisch | 64-Bit mit doppelter Genauigkeit, IEEE 754 |
Boolesch | bool |
False <True |
|
Textstring (kurz) | str unicode |
Unicode ( str als ASCII behandelt) |
Bis zu 1.500 Byte |
Textstring (lang) | db.Text |
– | Bis zu 1 Megabyte Nicht indexiert |
Bytestring (kurz) | db.ByteString |
Bytereihenfolge | Bis zu 1.500 Byte |
Bytestring (lang) | db.Blob |
– | Bis zu 1 Megabyte Nicht indexiert |
Datum und Uhrzeit | datetime.date datetime.time datetime.datetime |
Chronologisch | |
Geografischer Punkt | db.GeoPt |
Nach Breitengrad, dann Längengrad |
|
Postanschrift | db.PostalAddress |
Unicode | |
Telefonnummer | db.PhoneNumber |
Unicode | |
E-Mail-Adresse | db.Email |
Unicode | |
Nutzer eines Google-Kontos | users.User |
E-Mail-Adresse in Unicode-Reihenfolge |
|
Instant-Messaging-Handle | db.IM |
Unicode | |
Link | db.Link |
Unicode | |
Kategorie | db.Category |
Unicode | |
Bewertung | db.Rating |
Numerisch | |
Cloud Datastore-Schlüssel | db.Key |
Nach Pfadelementen (Art, Kennung, Art, Kennung...) |
|
Blobstore-Schlüssel | blobstore.BlobKey |
Bytereihenfolge | |
Null | NoneType |
– |
Wichtig: Es wird dringend empfohlen, kein UserProperty
-Attribut zu speichern, da dieses Attribut die E-Mail-Adresse und die eindeutige ID des Nutzers enthält. Wenn ein Nutzer seine E-Mail-Adresse ändert und Sie seinen alten gespeicherten User
mit dem neuen User
vergleichen, stimmen die Werte nicht überein.
Für Textstrings und nicht codierte Binärdaten (Bytestrings) unterstützt Cloud Datastore zwei Werttypen:
- Kurze Strings (bis zu 1.500 Byte) werden indexiert und können in Filterbedingungen der Abfrage und in Sortierfolgen verwendet werden.
- Lange Strings (bis zu 1 Megabyte) werden nicht indexiert und können nicht in Abfragefiltern und Sortierfolgen verwendet werden.
Blob
. Dieser ist nicht mit den Blobs identisch, die in der Blobstore API verwendet werden.
Wenn eine Abfrage ein Attribut mit Werten gemischter Typen umfasst, verwendet Cloud Datastore eine deterministische Sortierung auf Basis der internen Darstellungen:
- Nullwerte
- Festkommazahlen
- Ganzzahlen
- Datums- und Uhrzeitwerte
- Bewertungen
- Boolesche Werte
- Bytesequenzen
- Bytestring
- Unicode-String
- Blobstore-Schlüssel
- Gleitkommazahlen
- Geografische Punkte
- Nutzer von Google-Konten
- Cloud Datastore-Schlüssel
Da lange Textstrings und lange Bytestrings nicht indexiert werden, ist keine Reihenfolge definiert.
Mit Entitäten arbeiten
Anwendungen können Entitäten mit der Cloud Datastore API erstellen, abrufen, aktualisieren und löschen. Wenn die Anwendung den vollständigen Schlüssel für eine Entität kennt (oder ihn aus dem übergeordneten Schlüssel, der Art und der Kennung ableiten kann), kann sie mit dem Schlüssel direkt mit der Entität arbeiten. Eine Anwendung kann den Schlüssel einer Entität auch als Ergebnis einer Cloud Datastore-Abfrage erhalten. Weitere Informationen finden Sie auf der Seite Datenspeicherabfragen.
Entität erstellen
Zum Erstellen einer neuen Entität in Python müssen Sie eine Instanz einer Modellklasse anlegen, bei Bedarf deren Attribute angeben und ihre Methode put()
aufrufen, um sie in Datastore zu speichern. Wenn Sie den Schlüsselnamen der Entität angeben möchten, übergeben Sie das Argument "key_name" an den Konstruktor:
employee = Employee(key_name='asalieri',
first_name='Antonio',
last_name='Salieri')
employee.hire_date = datetime.datetime.now().date()
employee.attended_hr_training = True
employee.put()
Wenn Sie keinen Schlüsselnamen angeben, generiert Cloud Datastore automatisch eine numerische ID für den Schlüssel der Entität:
employee = Employee(first_name='Antonio',
last_name='Salieri')
employee.hire_date = datetime.datetime.now().date()
employee.attended_hr_training = True
employee.put()
Entität abrufen
Zum Abrufen einer Entität, die durch einen bestimmten Schlüssel identifiziert wird, übergeben Sie das Objekt Key
als Argument an die Funktion db.get()
. Das Objekt Key
kann mithilfe der Klassenmethode Key.from_path()
generiert werden.
Der vollständige Pfad ist eine Abfolge von Entitäten im Ancestor-Pfad, wobei jede Entität durch ihre Art (ein String) gefolgt von ihrer Kennung (Schlüsselname oder numerische ID) dargestellt wird:
address_k = db.Key.from_path('Employee', 'asalieri', 'Address', 1)
address = db.get(address_k)
db.get()
gibt eine Instanz der entsprechenden Modellklasse zurück. Bestätigen Sie, dass Sie die Modellklasse für die abzurufende Entität importiert haben.
Entität aktualisieren
Wenn Sie eine vorhandene Entität aktualisieren möchten, ändern Sie die Attribute des Objekts und rufen dann die zugehörige Methode put()
auf. Die bestehende Entität wird mit den Objektdaten überschrieben. Bei jedem Aufruf von put()
wird das ganze Objekt an Cloud Datastore gesendet.
Zum Löschen eines Attributs löschen Sie das Attribut aus dem Python-Objekt:
del address.postal_code
Speichern Sie dann das Objekt.
Entität löschen
Sie können eine Entität unter Angabe ihres Schlüssels mit der Funktion db.delete()
löschen:
address_k = db.Key.from_path('Employee', 'asalieri', 'Address', 1)
db.delete(address_k)
Es besteht auch die Möglichkeit, dafür die Methode delete()
der Entität aufzurufen:
employee_k = db.Key.from_path('Employee', 'asalieri')
employee = db.get(employee_k)
# ...
employee.delete()
Batchvorgänge
Für die Funktionen db.put()
, db.get()
und db.delete()
und ihre asynchronen Gegenstücke db.put_async()
, db.get_async()
und db.delete_async()
können Listenargumente angegeben werden, um einen Vorgang für mehrere Entitäten in einem einzigen Cloud Datastore-Aufruf auszuführen:
# A batch put.
db.put([e1, e2, e3])
# A batch get.
entities = db.get([k1, k2, k3])
# A batch delete.
db.delete([k1, k2, k3])
Batch-Vorgänge ändern nichts an Ihren Kosten. Jeder Schlüssel in einem Batchvorgang wird unabhängig davon in Rechnung gestellt, ob der Schlüssel vorhanden ist oder nicht. Die Größe der Entitäten in einem Vorgang wirkt sich nicht auf die Kosten aus.
Entitäten im Bulk löschen
Wenn Sie Entitäten in großen Mengen löschen müssen, empfehlen wir die Verwendung von Cloud Dataflow zum Löschen von Entitäten im Bulk.
Leere Liste verwenden
Für die NDB-Schnittstelle hat Cloud Datastore in der Vergangenheit eine leere Liste als ausgelassenes Attribut für statische und dynamische Attribute geschrieben. Zur Aufrechterhaltung der Abwärtskompatibilität bleibt dies das Standardverhalten. Wenn Sie dieses Verhalten global oder pro ListProperty-Basis überschreiben möchten, legen Sie für das Argument write_empty_list in der Attributklasse den Werttrue
fest. Die leere Liste wird dann in Cloud Datastore geschrieben und kann als leere Liste gelesen werden.
Für die DB-Schnittstelle waren Schreibvorgänge mit leeren Listen in der Vergangenheit bei dynamischen Attributen in keinem Fall zulässig. Wenn Sie solche Vorgänge ausführten, kam es zu einem Fehler. Dies bedeutet, dass kein Standardverhalten zwecks Abwärtskompatibilität für dynamische DB-Attribute beibehalten werden muss und Sie die leere Liste im dynamischen Modell ohne Änderungen einfach schreiben und lesen können.
Bei statischen DB-Attributen wurde die leere Liste jedoch als ausgelassenes Attribut geschrieben. Dieses Verhalten wird aus Gründen der Abwärtskompatibilität standardmäßig beibehalten.
Wenn Sie leere Listen für statische DB-Attribute aktivieren möchten, legen Sie für das Argument write_empty_list in der Attributklasse den Wert true
fest. Die leere Liste wird dann in Cloud Datastore geschrieben.