Metadati

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 API. Se al momento utilizzi la libreria client DB precedente, leggi il Guida alla migrazione da database a NDB

Datastore fornisce accesso programmatico ad alcuni dei suoi metadati supportare la metaprogrammazione, l'implementazione delle funzioni amministrative del backend, semplificare una memorizzazione nella cache coerente e scopi simili; puoi utilizzarlo, ad esempio, per creare un visualizzatore Datastore personalizzato per l'applicazione. I metadati disponibili include informazioni su gruppi di entità, spazi dei nomi, entità tipi e proprietà utilizzati dall'applicazione, oltre alla proprietà di archiviazione 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 restituito 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.
  • Sommario. Alcuni metadati nella dashboard non sono disponibili tramite le API; è vero anche il contrario.
  • Velocità. I dati ricevuti e le query vengono fatturati come Datastore ottiene e query. 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à necessarie all'incirca contemporaneamente a N query ordinarie ciascuna che restituisce una singola entità. Inoltre, query di rappresentazione delle strutture (query di proprietà non solo chiavi) sono più lente di query sulla proprietà solo per chiavi. L'ottenimento dei metadati del gruppo di entità è un po' più veloce rispetto al recupero di un un'entità regolare.

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 nell'intervallo specificato.
  • get_kinds() restituisce un elenco contenente nomi di tutti i tipi di entità di un'applicazione o quelli compresi 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 per tutti i le proprietà indicizzate dell'applicazione o quelle in un intervallo specificato associate di 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 precedente

Nel comportamento della versione del gruppo di entità legacy, la versione del gruppo di entità aumenta solo in caso di modifiche all'entità gruppo. Puoi utilizzare il comportamento dei metadati del gruppo di entità legacy per ad esempio, per mantenere una cache coerente di una query da predecessore complessa 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() può restituire None per un gruppo di entità che ha in cui non è mai stata scritta.

Le versioni dei gruppi di entità si ottengono 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 a 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. Tramite query su questi tipi speciali, puoi recuperare le entità contenenti i metadati.

Le entità restituite dalle query sui metadati vengono generate dinamicamente, in base a lo stato attuale di Datastore. Anche se puoi creare contenuti di Namespace, Kind o Property, qualsiasi il tentativo di archiviarle in Datastore avrà esito negativo con un BadRequestError un'eccezione.

Puoi eseguire query sui metadati utilizzando un oggetto che appartiene a uno dei due seguenti oggetti classi:

  • Un oggetto Query restituito da il metodo del corso Namespace.all(), Kind.all() o Property.all() (ereditato dal metodo della superclasse Model.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 dello 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à. Ciò ti consente di svolgere attività come funzioni amministrative in 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 designata dalla stringa vuota "": poiché la stringa vuota non è una chiave valida , questo spazio dei nomi è invece digitato con l'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__ 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. A facilitano le query, il modello Namespace fornisce i seguenti metodi delle classi:

Ad esempio, ecco l'implementazione della funzione helper get_namespaces(), che restituisce un elenco. contenente i nomi di tutti gli spazi dei nomi di un'applicazione (o quelli intervallo 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 gentili

Le query di tipo restituiscono entità di tipo __kind__ il cui nome della chiave è il nome della un tipo di entità. Le query di questo tipo sono implicitamente limitate alla query attuale dello spazio dei nomi e supporta l'applicazione di filtri solo per intervalli oltre l'__key__ pseudoproprietà. 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à della stringa kind_name, calcolato dalla chiave dell'entità, restituisce il nome dell'entità corrispondente gentile. Per facilitare l'esecuzione di query, il modello Kind fornisce la seguente classe metodo:

Ad esempio, ecco l'implementazione della funzione helper get_kinds(), che restituisce un elenco. contenente i nomi di tutti i tipi di entità di un'applicazione (o quelli nel intervallo 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]

L'esempio seguente stampa tutti i tipi i cui nomi iniziano con una lettera minuscola lettera:

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 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). La l'entità che rappresenta la proprietà P di tipo K viene creata come segue:

  • La chiave dell'entità ha il tipo __property__ e il nome della chiave P.
  • La chiave dell'entità padre 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:

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 sulla proprietà dipende dal fatto che si tratti o meno di una query soltanto chiavi o un solo non chiavi (rappresentazione della proprietà) query, come descritto nelle sottosezioni di seguito.

Query proprietà: solo chiavi

Le query proprietà solo chiavi restituiscono una chiave per ogni proprietà indicizzata di una 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 implicitamente limitate allo spazio dei nomi corrente e supportano l'applicazione di filtri solo per intervalli al di sopra della pseudoproprietà __key__, in cui I tasti indicano entità __kind__ o __property__. I risultati possono essere ordinati 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é proprietà di tipo Account e Product, perché non rientrano nell'intervallo specificato per query.

Le query proprietà supportano anche il filtro dei predecessori su __kind__ o __property__, per limitare i risultati della query a un singolo tipo o proprietà. Tu puoi usarlo, ad esempio, per ottenere le proprietà associate a una determinata entità come nell'esempio seguente:

(un'implementazione della funzione helper 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 della proprietà: solo non 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 richiesta query con solo chiavi, insieme a un'altra proprietà property_representation che restituisce 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 corrispondono alle classi di proprietà. più possono essere mappate alla stessa rappresentazione. Ad esempio, StringProperty e PhoneNumberProperty entrambi usano 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 elenco
StringListProperty Rappresentazione dell'elemento elenco

Ad esempio, ecco l'implementazione della funzione helper get_representations_of_kind(), che restituisce un dizionario contenente le rappresentazioni per tutti i delle proprietà indicizzate dell'applicazione (o nell'intervallo tra due nomi, start e end) associati 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