Nota: Gli sviluppatori che creano nuove applicazioni sono vivamente incoraggiati a utilizzare il Libreria client NDB, che offre numerosi vantaggi rispetto a questa libreria client, come la memorizzazione automatica nella cache delle entità tramite tramite Google Cloud CLI o tramite l'API Compute Engine. Se al momento utilizzi la libreria client DB precedente, leggi il Guida alla migrazione da DB a NDB
Datastore fornisce accesso programmatico ad alcuni dei suoi metadati per supportare la metaprogrammazione, implementare funzioni amministrative di backend, semplificare la memorizzazione nella cache coerente e scopi simili. Puoi utilizzarlo, ad esempio, per creare un visualizzatore Datastore personalizzato per la tua applicazione. I metadati disponibili includono informazioni su gruppi di entità, spazi dei nomi, tipi di entità e proprietà utilizzati dalla tua applicazione, nonché le rappresentazioni delle proprietà per ogni proprietà.
La dashboard di Datastore in la console Google Cloud fornisce anche alcuni metadati sulla tua applicazione, ma i dati mostrati sono diversi da alcuni aspetti importanti che vengono restituiti da queste funzioni.
- Novità. La lettura dei metadati utilizzando l'API recupera i dati correnti, mentre quelli della dashboard viene aggiornata una volta al giorno.
- Contenuti. Alcuni metadati nella dashboard non sono disponibili tramite le API; è vero anche il contrario.
- Velocità. Le query e i get dei metadati vengono fatturati nello stesso modo delle query e dei get di Datastore. Query dei metadati che recuperano informazioni su spazi dei nomi, tipi e proprietà l'esecuzione è generalmente lenta. Come regola generale, aspettati una query sui metadati che restituisce N entità da impiegare quasi nello stesso tempo di N query ordinarie ciascuna che restituisce una singola entità. Inoltre, le query di rappresentazione delle strutture (query sulle strutture non solo con chiavi) sono più lente rispetto alle query sulle strutture solo con chiavi. I metadati dei gruppi di entità sono leggermente più veloci rispetto a quelli di un'entità normale.
Funzioni helper
Le seguenti funzioni ottengono informazioni sui metadati:
get_entity_group_version()
ottiene un numero di versione per un gruppo di entità; Ciò è utile per scoprire se qualsiasi entità del gruppo è cambiata dall'ultima volta che hai scaricato la versione numero.get_namespaces()
restituisce un elenco contenente i nomi di tutti gli spazi dei nomi di un'applicazione o di quelli nell'intervallo specificato.get_kinds()
restituisce un elenco contenente i nomi di tutti i tipi di entità di un'applicazione o di quelli in un intervallo specificato.get_properties_of_kind()
restituisce un elenco contenente i nomi di tutte le istanze (o quelle in un intervallo specificato) associate a una determinata entità gentile. Le proprietà non indicizzate non sono incluse.get_representations_of_kind()
restituisce un dizionario contenente le rappresentazioni di tutte le proprietà indicizzate di un'applicazione o quelle in un intervallo specificato associato a un determinato tipo di entità. Il dizionario mappa il nome di ogni proprietà a un elenco delle rappresentazioni della proprietà. Le proprietà non indicizzate non sono incluse.
Metadati del gruppo di entità
Cloud Datastore fornisce l'accesso alla "versione" di un'entità gruppo, un numero assolutamente positivo che è garantito in aumento a ogni modifica al gruppo di entità.
L'esempio seguente mostra come ottenere la versione di un gruppo di entità:
from google.appengine.ext import db
from google.appengine.ext.db import metadata
class Simple(db.Model):
x = db.IntegerProperty()
entity1 = Simple(x=11)
entity1.put()
# Print entity1's entity group version
print 'version', metadata.get_entity_group_version(entity1)
# Write to a different entity group
entity2 = Simple(x=22)
entity2.put()
# Will print the same version, as entity1's entity group has not changed
print 'version', metadata.get_entity_group_version(entity1)
# Change entity1's entity group by adding a new child entity
entity3 = Simple(x=33, parent=entity1.key())
entity3.put()
# Will print a higher version, as entity1's entity group has changed
print metadata.get_entity_group_version(entity1)
Comportamento legacy
Nel comportamento precedente della versione del gruppo di entità, la versione del gruppo di entità aumenta solo in caso di modifiche al gruppo di entità. Il comportamento precedente dei metadati dei gruppi di entità potrebbe essere utilizzato, ad esempio, per mantenere una cache coerente di una query sull'antenato complessa in un gruppo di entità.
Questo esempio memorizza nella cache i risultati della query (un conteggio dei risultati corrispondenti) e utilizza la classe comportamento precedente delle versioni dei gruppi di entità per utilizzare il valore memorizzato nella cache, se attuale:
from google.appengine.api import memcache
from google.appengine.ext import db
from google.appengine.ext.db import metadata
def count_entity_group(entity_group_key):
"""Count the entities in the specified entity group."""
# Check if we have a cached version of the current entity group count
cached = memcache.get(str(entity_group_key))
if cached:
(version, count) = cached
# Is the cached value for the current version?
if version == metadata.get_entity_group_version(entity_group_key):
return count
def tx():
# Need to actually count entities. Using a transaction to get a consistent
# count and entity group version.
count = db.Query(keys_only=True).ancestor(entity_group_key).count(limit=5000)
# Cache the count and the entity group version
version = metadata.get_entity_group_version(entity_group_key)
memcache.set(str(entity_group_key), (version, count))
return count
return db.run_in_transaction(tx)
get_entity_group_version()
potrebbe restituire None
per un gruppo di entità in cui non è stata mai eseguita la scrittura.
Le versioni dei gruppi di entità vengono ottenute chiamando get()
su una pseudo-entità speciale
che contiene una proprietà __version__
. Consulta la documentazione di riferimento su
EntityGroup per i dettagli.
Query dei metadati
Se le funzioni helper descritte nella sezione precedente non soddisfano le tue
di metadati, puoi inviare richieste di metadati più elaborate o flessibili con
una query esplicita sui metadati. In Python, le classi del modello per queste query sono
definita nel
google.appengine.ext.db.metadata
pacchetto. Questi modelli forniscono tipi di entità speciali riservati alle query sui metadati:
Classe modello | Tipo di entità |
---|---|
Namespace |
__namespace__ |
Kind |
__kind__ |
Property |
__property__ |
Questi modelli e tipi non saranno in conflitto con altri nomi con gli stessi nomi che potrebbero esistere già nella tua applicazione. Eseguendo query su questi tipi speciali, puoi recuperare le entità contenenti i metadati desiderati.
Le entità restituite dalle query sui metadati vengono generate in modo dinamico in base allo stato corrente di Datastore. Sebbene sia possibile creare istanze locali delle classi di modelli Namespace
, Kind
o Property
, qualsiasi tentativo di archiviarle in Datastore non andrà a buon fine con un'eccezione BadRequestError
.
Puoi eseguire query sui metadati utilizzando un oggetto che appartiene a uno dei due seguenti oggetti classi:
- Un oggetto
Query
restituito dal metodo della classeNamespace.all()
,Kind.all()
oProperty.all()
(ereditato dal metodo della superclasseModel.all()
) - Un oggetto
GqlQuery
per query in stile GQL
L'esempio seguente restituisce i nomi di tutti i tipi di entità in un'applicazione:
from google.appengine.ext import db
from google.appengine.ext.db.metadata import Kind
for k in Kind.all():
print "kind: '%s'" % k.kind_name
Query sullo spazio dei nomi
Se la tua applicazione utilizza l'API Namespaces , puoi utilizzare una query dello spazio dei nomi per trovare tutti gli spazi dei nomi utilizzati le entità. In questo modo puoi eseguire attività come le funzioni amministrative su più spazi dei nomi.
Le query dello spazio dei nomi restituiscono entità di tipo speciale __namespace__
la cui chiave
name è il nome di uno spazio dei nomi. Un'eccezione è lo spazio dei nomi predefinito designato dalla stringa vuota ""
: poiché la stringa vuota non è un nome di chiave valido, questo spazio dei nomi è associato all'ID numerico 1
. Query di questo
il tipo supporta l'applicazione di filtri solo per gli intervalli sopra la pseudoproprietà speciale.
__key__
, il cui valore è la chiave dell'entità. I risultati possono essere ordinati per
valore di __key__
in ordine crescente (ma non decrescente). Poiché __namespace__
entità
non hanno proprietà, le query solo chiavi e non solo chiavi restituiscono lo stesso
informazioni.
Le entità dello spazio dei nomi sono istanze della classe modello
google.appengine.ext.db.metadata.Namespace
La proprietà della stringa
namespace_name
,
calcolato dalla chiave dell'entità, restituisce il nome dello spazio dei nomi corrispondente.
Se la chiave ha l'ID numerico 1
, la proprietà restituisce la stringa vuota. Per
facilitare le query, il modello Namespace
fornisce i seguenti metodi di classe:
Namespace.key_for_namespace()
genera una chiave__namespace__
da un nome dello spazio dei nomi.Namespace.key_to_namespace()
restituisce il nome dello spazio dei nomi corrispondente a una determinata chiave__namespace__
.
Ad esempio, di seguito è riportata l'implementazione della funzione di supporto
get_namespaces()
, che restituisce un elenco
contenente i nomi di tutti gli spazi dei nomi di un'applicazione (o quelli nell'
intervallo compreso tra due nomi specificati, start
e end
):
from google.appengine.ext import db
from google.appengine.ext.db.metadata import Namespace
def get_namespaces(start=None, end=None):
# Start with unrestricted namespace query
q = Namespace.all()
# Limit to specified range, if any
if start is not None:
q.filter('__key__ >=', Namespace.key_for_namespace(start))
if end is not None:
q.filter('__key__ <', Namespace.key_for_namespace(end))
# Return list of query results
return [ns.namespace_name for ns in q]
Query sui tipi
Le query sui tipi restituiscono entità di tipo __kind__
il cui nome della chiave è il nome di un tipo di entità. Le query di questo tipo sono limitate implicitamente allo spazio dei nomi corrente e supportano l'applicazione di filtri solo per gli intervalli della pseudoproprietà __key__
. I risultati possono essere ordinati in ordine crescente (ma non in ordine decrescente)
Valore __key__
. Poiché le entità __kind__
non hanno proprietà, vengono utilizzate solo entrambe le chiavi
e non solo chiavi restituiscono le stesse informazioni.
Le entità di tipo sono istanze della classe del modello
google.appengine.ext.db.metadata.Kind
La proprietà stringa kind_name
, calcolata dalla chiave dell'entità, restituisce il nome del tipo di entità corrispondente. Per facilitare le query, il modello Kind
fornisce i seguenti metodi di classe:
Kind.key_for_kind()
genera una chiave__kind__
da un nome di tipo.Kind.key_to_kind()
restituisce il nome del tipo corrispondente a una determinata chiave__kind__
.
Ad esempio, di seguito è riportata l'implementazione della funzione di supporto
get_kinds()
, che restituisce un elenco
contenente i nomi di tutti i tipi di entità di un'applicazione (o quelli nell'
intervallo compreso tra due nomi specificati, start
e end
):
from google.appengine.ext import db
from google.appengine.ext.db.metadata import Kind
def get_kinds(start=None, end=None):
# Start with unrestricted kind query
q = Kind.all()
# Limit to specified range, if any
if start is not None and start != '':
q.filter('__key__ >=', Kind.key_for_kind(start))
if end is not None:
if end == '':
return [] # Empty string is not a valid kind name, so can't filter
q.filter('__key__ <', Kind.key_for_kind(end))
# Return list of query results
return [k.kind_name for k in q]
Il seguente esempio stampa tutti i tipi i cui nomi iniziano con una lettera minuscola:
from google.appengine.ext import db
from google.appengine.ext.db.metadata import Kind
# Start with unrestricted kind query
q = Kind.all()
# Limit to lowercase initial letters
q.filter('__key__ >=', Kind.key_for_kind('a'))
endChar = chr(ord('z') + 1) # Character after 'z'
q.filter('__key__ <', Kind.key_for_kind(endChar))
# Print query results
for k in q:
print k.kind_name
Query sulle proprietà
Le query di proprietà restituiscono entità di tipo __property__
che indicano
proprietà associate a un tipo di entità (se o
tali proprietà non sono attualmente definite nel modello del tipo). L'entità che rappresenta la proprietà P di tipo K viene creata nel seguente modo:
- La chiave dell'entità ha il tipo
__property__
e il nome della chiave P. - La chiave dell'entità principale ha il tipo
__kind__
e il nome della chiave K.
Le entità della proprietà sono istanze della classe del modello
google.appengine.ext.db.metadata.Property
Le proprietà della stringa
kind_name
e property_name
,
calcolati dalla chiave dell'entità, restituiscono i nomi del tipo corrispondente
proprietà. Il modello Property
offre quattro metodi delle classi per semplificare la creazione
ed esaminando __property__
chiavi:
Property.key_for_kind()
genera una chiave__kind__
principale per le chiavi__property__
di un tipo di entità specificato.Property.key_for_property()
genera una chiave__property__
per un tipo e una proprietà specificati.Property.key_to_kind()
restituisce il nome del tipo associato a una chiave__property__
.Property.key_to_property()
restituisce il nome della proprietà associata a una chiave__property__
(oNone
se la chiave specifica solo un tipo).
L'esempio seguente illustra questi metodi:
from google.appengine.ext import db
from google.appengine.ext.db.metadata import Property
class Employee(db.Model):
name = db.StringProperty()
ssn = db.IntegerProperty()
employee_key = Property.key_for_kind("Employee")
employee_name_key = Property.key_for_property("Employee", "Name")
Property.key_to_kind(employee_key) # Returns "Employee"
Property.key_to_property(employee_name_key) # Returns "Name"
Il comportamento di una query sulle proprietà dipende dal fatto che si tratti di una query solo chiavi o non solo chiavi (rappresentazione della proprietà), come descritto nelle sezioni seguenti.
Query proprietà: solo chiavi
Le query sulle proprietà solo chiavi restituiscono una chiave per ogni proprietà indicizzata di un tipo di entità specificato. Le proprietà non indicizzate non sono incluse. Le seguenti un esempio mostra i nomi di tutti i tipi di entità di un'applicazione proprietà associate a ciascuno:
from google.appengine.ext import db
from google.appengine.ext.db.metadata import Property
# Create unrestricted keys-only property query
q = Property.all(keys_only=True)
# Print query results
for p in q:
print "%s: %s" % (Property.key_to_kind(p), Property.key_to_property(p))
Le query di questo tipo sono limitate implicitamente allo spazio dei nomi corrente e supportano il filtro solo per gli intervalli della pseudoproprietà __key__
, dove le chiavi indicano entità __kind__
o __property__
. I risultati possono essere
Ordinate in base al valore __key__
crescente (ma non decrescente). Filtro applicato
alle coppie tipo-proprietà, ordinate prima per tipo e la seconda per proprietà: per
supponi di avere un'entità con le seguenti proprietà:
- tipo
Account
con proprietàbalance
company
- tipo
Employee
con proprietàname
ssn
- tipo
Invoice
con proprietàdate
amount
- tipo
Manager
con proprietàname
title
- tipo
Product
con proprietàdescription
price
La query per restituire i dati della proprietà avrebbe il seguente aspetto:
from google.appengine.ext import db
from google.appengine.ext.db.metadata import Property
# Start with unrestricted keys-only property query
q = Property.all(keys_only=True)
# Limit range
q.filter('__key__ >=', Property.key_for_property("Employee", "salary"))
q.filter('__key__ <=', Property.key_for_property("Manager", "salary"))
# Print query results
for p in q:
print "%s: %s" % (Property.key_to_kind(p), Property.key_to_property(p))
La query precedente restituirà quanto segue:
Employee: ssn
Invoice: date
Invoice: amount
Manager: name
Tieni presente che i risultati non includono la proprietà name
di tipo Employee
e la proprietà title
di tipo Manager
, né le proprietà di tipi
Account
e Product
, perché non rientrano nell'intervallo specificato per la
query.
Le query proprietà supportano anche il filtro dei predecessori su un __kind__
o
__property__
, per limitare i risultati della query a un singolo tipo o proprietà. Puoi utilizzarlo, ad esempio, per recuperare le proprietà associate a un determinato tipo di entità, come nell'esempio seguente:
get_properties_of_kind()
)
from google.appengine.ext import db
from google.appengine.ext.db.metadata import Property
def get_properties_of_kind(kind, start=None, end=None):
# Start with unrestricted keys-only property query
q = Property.all(keys_only=True)
# Limit to specified kind
q.ancestor(Property.key_for_kind(kind))
# Limit to specified range, if any
if start is not None and start != '':
q.filter('__key__ >=', Property.key_for_property(kind, start))
if end is not None:
if end == '':
return [] # Empty string is not a valid property name, so can't filter
q.filter('__key__ <', Property.key_for_property(kind, end))
# Return list of query results
return [Property.key_to_property(p) for p in q]
Query sulle proprietà: non solo chiavi (rappresentazione della proprietà)
Query su proprietà non solo chiavi, note come query di rappresentazione della proprietà,
restituiscono informazioni aggiuntive sulle rappresentazioni utilizzate da ogni proprietà "kind"
. Le proprietà non indicizzate non sono incluse. L'entità restituita per la proprietà
P di tipo K ha la stessa chiave di una corrispondente
query solo chiavi,
oltre a una proprietà property_representation
aggiuntiva che restituisce le rappresentazioni della proprietà. Il valore di questa proprietà è un'istanza di classe
StringListProperty
contenente una stringa per ogni rappresentazione
proprietà P trovata in qualsiasi entità di tipo K.
Tieni presente che le rappresentazioni non sono uguali ai classi di proprietà; più classi di proprietà possono essere associate alla stessa rappresentazione. Ad esempio,
StringProperty
e
PhoneNumberProperty
utilizzano entrambi la rappresentazione STRING
.
La seguente tabella mappa le classi di proprietà alle relative rappresentazioni:
Classe della struttura | Rappresentazione |
---|---|
IntegerProperty |
INT64 |
FloatProperty |
DOUBLE |
BooleanProperty |
BOOLEAN |
StringProperty |
STRING |
ByteStringProperty |
STRING |
DateProperty |
INT64 |
TimeProperty |
INT64 |
DateTimeProperty |
INT64 |
GeoPtProperty |
POINT |
PostalAddressProperty |
STRING |
PhoneNumberProperty |
STRING |
EmailProperty |
STRING |
UserProperty |
USER |
IMProperty |
STRING |
LinkProperty |
STRING |
CategoryProperty |
STRING |
RatingProperty |
INT64 |
ReferenceProperty SelfReferenceProperty |
REFERENCE |
blobstore.BlobReferenceProperty |
STRING |
ListProperty |
Rappresentazione dell'elemento dell'elenco |
StringListProperty |
Rappresentazione dell'elemento dell'elenco |
Ad esempio, di seguito è riportata l'implementazione della funzione di supporto
get_representations_of_kind()
,
che restituisce un dizionario contenente le rappresentazioni di tutte le proprietà indicizzate di un'applicazione (o quelle nell'intervallo compreso tra due nomi specificati, start
e end
) associate a un determinato tipo di entità. Il dizionario
Mappa il nome di ogni proprietà a un elenco delle rappresentazioni di quella proprietà:
from google.appengine.ext import db
from google.appengine.ext.db.metadata import Property
def get_representations_of_kind(kind, start=None, end=None):
# Start with unrestricted non-keys-only property query
q = Property.all()
# Limit to specified kind
q.ancestor(Property.key_for_kind(kind))
# Limit to specified range, if any
if start is not None and start != '':
q.filter('__key__ >=', Property.key_for_property(kind, start))
if end is not None:
if end == '':
return [] # Empty string is not a valid property name, so can't filter
q.filter('__key__ <', Property.key_for_property(kind, end))
# Initialize result dictionary
result = {}
# Add query results to dictionary
for p in q:
result[p.property_name] = p.property_representation
# Return dictionary
return result