Riferimento alle proprietà delle entità

Firestore in modalità Datastore (Datastore) supporta una vasta gamma di tipi di dati per i valori delle proprietà. Questi includono: tra gli altri:

  • Numeri interi
  • Numeri con virgola mobile
  • Stringhe
  • Date
  • Dati binari

Per un elenco completo dei tipi, vedi Proprietà e tipi di valori:

Proprietà e tipi di valore

I valori dei dati associati a un'entità sono costituiti da una o più proprietà. Ogni proprietà ha un nome e uno o più valori. Una proprietà può avere valori di più tipi e due entità possono avere valori di tipi diversi per la stessa proprietà. Le proprietà possono essere indicizzate o non indicizzate (le query che ordinano o filtrano i dati su una proprietà P ignoreranno le entità in cui P non è indicizzato). Un'entità può avere al massimo 20.000 proprietà indicizzate.

Sono supportati i seguenti tipi di valori:

Quando una query coinvolge una proprietà con valori di tipi misti, Datastore utilizza un ordinamento deterministico basato sulle rappresentazioni interne:

  1. Valori null
  2. Numeri a virgola fissa
    • Numeri interi
    • Date e ore
  3. Valori booleani
  4. Sequenze byte
    • Stringa Unicode
    • Chiavi dell'archivio BLOB
  5. Numeri con virgola mobile
  6. Chiavi Datastore

Poiché le stringhe di testo lunghe e le stringhe di byte lunghi non vengono indicizzate, non è stato definito un ordinamento.

Tipi di proprietà

NDB supporta i seguenti tipi di proprietà:

Tipo di struttura Descrizione
IntegerProperty Numero intero a 64 bit con segno
FloatProperty Numero in virgola mobile a precisione doppia
BooleanProperty Booleano
StringProperty Stringa Unicode; fino a 1500 byte, indicizzati
TextProperty Stringa Unicode; lunghezza illimitata, non indicizzato
BlobProperty Stringa di byte non interpretata:
se imposti indexed=True, fino a 1500 byte, indicizzati;
se indexed è False (valore predefinito), lunghezza illimitata, non indicizzato.
Argomento parola chiave facoltativo: compressed.
DateTimeProperty Data e ora (vedi Proprietà data e ora)
DateProperty Data (vedi Proprietà data e ora)
TimeProperty Ora (vedi Proprietà data e ora)
GeoPtProperty Posizione geografica. Questo è un oggetto ndb.GeoPt. L'oggetto ha attributi lat e lon, entrambi in virgola mobile. Puoi costruirne uno con due valori mobili, ndb.GeoPt(52.37, 4.88) o con una stringa ndb.GeoPt("52.37, 4.88"). (Si tratta della stessa classe db.GeoPt
KeyProperty Chiave datastore
Argomento facoltativo della parola chiave: kind=kind, per richiedere le chiavi assegnate a questa proprietà hanno sempre il tipo indicato. Può essere un o una sottoclasse del modello.
BlobKeyProperty Chiave archivio BLOB
Corrisponde a BlobReferenceProperty nell'API db precedente, ma il valore della proprietà è BlobKey anziché BlobInfo; puoi creare una BlobInfo utilizzando BlobInfo(blobkey)
UserProperty Oggetto utente.
StructuredProperty Include un tipo di modello all'interno di un altro, per valore (consulta Proprietà strutturate)
LocalStructuredProperty Come StructuredProperty, ma la rappresentazione su disco è un blob opaco e non è indicizzata (consulta Proprietà strutturate).
Argomento parola chiave facoltativo: compressed.
JsonProperty Il valore è un oggetto Python (ad esempio un elenco, un dict o una stringa) serializzabile usando il modulo json di Python. Datastore la serializzazione JSON come blob. Non indicizzato per impostazione predefinita.
Argomento parola chiave facoltativo: compressed.
PickleProperty Il valore è un oggetto Python (ad esempio un elenco, un dict o una stringa) serializzabile usando il protocollo pickle di Python; Datastore la serializzazione del sottaceto come blob. Non indicizzato per impostazione predefinita.
Argomento parola chiave facoltativo: compressed.
GenericProperty Valore generico
Usato principalmente da Expando ma anche utilizzabile in modo esplicito. Il suo tipo può essere uno di int, long, float, bool, str unicode, datetime, Key BlobKey, GeoPt, User, None.
ComputedProperty Valore calcolato da altre proprietà da una funzione definita dall'utente. (vedi Proprietà calcolate).

Alcune di queste proprietà hanno un argomento parola chiave facoltativo, compressed. Se la proprietà ha compressed=True, i dati vengono compressi con gzip su disco. Occupa meno spazio ma ha bisogno di CPU per la codifica/decodifica in fase di scrittura operazioni di lettura.

Sia la compressione che la decompressione sono "lazy"; una proprietà compressa verrà decompresso solo la prima volta che vi accederai. Se leggi un'entità contenente un valore di proprietà compresso lo riscrivi senza accedere alla proprietà compressa, non sia decompresso e compresso. La strategia in contesto Cache partecipa a questo schema lazy, memcache archivia sempre il valore compresso per le proprietà compresse.

A causa del tempo di CPU aggiuntivo necessario per la compressione, di solito il è preferibile utilizzare proprietà compresse solo se i dati sono troppo grandi per farne a meno. Ricorda che la compressione basata su gzip solitamente non sono efficaci per le immagini e altri dati multimediali, i formati vengono già compressi utilizzando un modello algoritmo di compressione (ad es. JPEG per le immagini).

Opzioni proprietà

La maggior parte dei tipi di proprietà supporta alcuni argomenti standard. Il primo è un argomento posizionale facoltativo che specifica Nome datastore. Puoi utilizzare questa opzione per assegnare alla proprietà un nome diverso Datastore dal punto di vista dell'applicazione. Un uso comune è la riduzione dello spazio in Datastore, consentendo Datastore utilizza nomi di proprietà abbreviati, mentre il codice utilizza più lunghi e più significativi. Ad esempio,

class Employee(ndb.Model):
    full_name = ndb.StringProperty('n')
    retirement_age = ndb.IntegerProperty('r')

Ciò è particolarmente utile per le proprietà ripetute per le quali prevedi molti valori per entità.

Inoltre, la maggior parte dei tipi di proprietà supporta i seguenti argomenti delle parole chiave:

Argomento Tipo Predefinito Descrizione
indexed bool Di solito a True Includi la proprietà negli indici di Datastore; se False, non è possibile eseguire query sui valori ma le scritture sono più veloci. Non tutti i tipi di proprietà supportano l'indicizzazione. l'impostazione del criterio indexed su True non riesce per questi motivi.
Le proprietà non indicizzate costano meno operazioni di scrittura rispetto alle proprietà indicizzate.
repeated bool False Il valore della proprietà è un elenco Python contenente i valori del tipo sottostante (consulta la sezione Proprietà ripetute).
Non può essere combinata con required=True o default=True.
required bool False È necessario specificare un valore per la proprietà.
default Tipo sottostante della proprietà Nessuno Valore predefinito della proprietà se non è specificato esplicitamente.
choices Elenco di valori del tipo sottostante None Elenco facoltativo di valori consentiti.
validator Funzione None

Funzione facoltativa per convalidare ed eventualmente forzare il valore.

Verrà chiamata con argomenti (prop, value) e dovrebbe restituire il valore valore (possibilmente forzato) o sollevare un'eccezione. Richiamo della funzione su un valore forzato non dovrebbe modificare ulteriormente il valore. Ad esempio, la restituzione di value.strip() o value.lower() va bene, ma non value + '$'. Potrebbe anche restituire None, che significa "nessuna modifica". Vedi anche Scrittura di sottoclassi di proprietà

verbose_name string None

Etichetta HTML facoltativa da utilizzare nei framework di moduli web come jinja2.

Proprietà ripetute

Qualsiasi proprietà con repeated=True diventa una proprietà ripetuta. La proprietà accetta un elenco di valori del tipo sottostante, anziché un singolo valore. Ad esempio, il valore di una proprietà definita con IntegerProperty(repeated=True) è un elenco di numeri interi.

Datastore potrebbe visualizzare più valori per una proprietà di questo tipo. Viene creato un record di indice separato per ogni valore. Questo influisce sulla semantica della query; vedi Esecuzione di query su proprietà ripetute per vedere un esempio.

In questo esempio viene utilizzata una proprietà ripetuta:

class Article(ndb.Model):
    title = ndb.StringProperty()
    stars = ndb.IntegerProperty()
    tags = ndb.StringProperty(repeated=True)
...
article = Article(
    title='Python versus Ruby',
    stars=3,
    tags=['python', 'ruby'])
article.put()

Viene creata un'entità Datastore con i seguenti contenuti:

assert article.title == 'Python versus Ruby'
assert article.stars == 3
assert sorted(article.tags) == sorted(['python', 'ruby'])

Quando esegui una query per la proprietà tags, questa entità soddisferà una query per 'python' o 'ruby'.

Quando aggiorni una proprietà ripetuta, puoi assegnarle un nuovo elenco o modificare l'elenco esistente. Quando assegni un nuovo elenco, i tipi di elementi dell'elenco vengono convalidato immediatamente. Tipi di articoli non validi (ad esempio, l'assegnazione di [1, 2] a art.tags sopra) solleva un'eccezione. Quando modifichi l'elenco, la modifica non viene convalidata immediatamente. Il valore verrà invece convalidato quando scrivi l'entità in Datastore.

Datastore conserva l'ordine degli elementi dell'elenco in un ambiente , in modo da poter assegnare un significato al loro ordinamento.

Proprietà data e ora

Sono disponibili tre tipi di proprietà per l'archiviazione di dati valori:

  • DateProperty
  • TimeProperty
  • DateTimeProperty

Questi assumono valori appartenenti alle classi corrispondenti (date, time, datetime) del modulo datetime standard Python. Il più generale dei tre è DateTimeProperty, che indicano sia una data di calendario che un'ora del giorno; gli altri, a volte, sono utili per scopi speciali che richiedono solo una data (ad esempio la data di nascita) o solo un orario (ad esempio l'orario di una riunione). Per motivi tecnici, DateProperty e TimeProperty sono sottoclassi di DateTimeProperty, ma non devi dipendere da questa relazione di ereditarietà, (nota che differisce dalle relazioni di ereditarietà tra le classi sottostanti definite dal modulo datetime stesso).

Nota: Gli orari orologio di App Engine sono sempre espressi in valori universali coordinati ora (UTC). Diventa pertinente se utilizzi la data o l'ora correnti (datetime.datetime.now()) come valore o converti tra oggetti data/ora e timestamp POSIX o tuple temporali. Tuttavia, in Datastore non vengono archiviate informazioni esplicite sul fuso orario, quindi, se fai attenzione, puoi usarli per rappresentare l'ora locale in qualsiasi fuso orario, se utilizzi l'ora corrente o le conversioni.

Ognuna di queste proprietà ha due opzioni aggiuntive per le parole chiave booleane:

Opzione Descrizione
auto_now_add Imposta la proprietà sulla data/ora corrente quando viene creata l'entità. Puoi eseguire manualmente l'override proprietà. Quando l'entità viene aggiornata, la proprietà non cambia. Per questo comportamento, usa auto_now.
auto_now Imposta la proprietà sulla data/ora corrente quando viene creata l'entità ogni volta che viene aggiornato.

Queste opzioni non possono essere combinate con repeated=True. Entrambi sono impostati su False per impostazione predefinita. se entrambi sono impostati su True, auto_now ha la precedenza. È possibile sostituire il valore di una proprietà con auto_now_add=True, ma non per uno con auto_now=True. Il valore automatico non viene generato finché l'entità non viene scritta. ovvero non forniscono valori predefiniti dinamici. Questi dettagli sono diversi dall'API del database precedente.

Nota: Quando una transazione scrive una proprietà con auto_now_add=True non riesce e viene riprovato in un secondo momento, riutilizza lo stesso valore dell'ora del tentativo originale anziché aggiornarlo con il momento del nuovo tentativo. Se la transazione non riesce definitivamente, il valore della proprietà sarà comunque impostato nella copia in memoria dell'entità.

Proprietà strutturate

Puoi strutturare le proprietà di un modello. Ad esempio, puoi definire una classe di modello Contact contenente un elenco di indirizzi, ognuno con una struttura interna. Proprietà strutturate (tipo StructuredProperty) ti lascio fare: Ad esempio:

class Address(ndb.Model):
    type = ndb.StringProperty()  # E.g., 'home', 'work'
    street = ndb.StringProperty()
    city = ndb.StringProperty()
...
class Contact(ndb.Model):
    name = ndb.StringProperty()
    addresses = ndb.StructuredProperty(Address, repeated=True)
...
guido = Contact(
    name='Guido',
    addresses=[
        Address(
            type='home',
            city='Amsterdam'),
        Address(
            type='work',
            street='Spear St',
            city='SF')])

guido.put()

Viene creata una singola entità Datastore con le seguenti proprietà:

assert guido.name == 'Guido'
addresses = guido.addresses
assert addresses[0].type == 'home'
assert addresses[1].type == 'work'
assert addresses[0].street is None
assert addresses[1].street == 'Spear St'
assert addresses[0].city == 'Amsterdam'
assert addresses[1].city == 'SF'

La lettura di questa entità ricostruisce l'originale Entità Contact esattamente. Anche se le istanze Address sono definite usando la stessa sintassi delle classi del modello, non sono entità a tutti gli effetti. Non hanno chiavi proprie in Datastore. Non possono essere recuperate indipendentemente da Contact l'entità alla quale appartengono. Un'applicazione può, tuttavia, interrogare i valori dei propri singoli campi; vedi Filtro dei valori delle proprietà strutturate. Tieni presente che address.type, address.street, e address.city sono visti come array paralleli da Punto di vista di Datastore, ma la libreria NDB nasconde questo aspetto e genera l'elenco corrispondente di istanze Address.

Puoi specificare la consueta opzioni proprietà per le proprietà strutturate (tranne indexed). Il nome Datastore è secondo argomento posizionale in questo caso (la prima è la classe del modello utilizzata per definire la sottostruttura).

Quando non devi eseguire query sulle proprietà interne di una struttura, puoi usare una proprietà strutturata locale (LocalStructuredProperty) . Se sostituisci StructuredProperty con LocalStructuredProperty nell'esempio precedente, il comportamento del codice Python è lo stesso, ma Datastore vede solo un blob opaco per ogni indirizzo. L'entità guido creata nell'esempio essere archiviati come segue: nome = 'Guido' address = &lt;opaque blob for {&#39;type&#39;: &#39;home&#39;, &#39;city&#39;: &#39;Amsterdam&#39;}&gt; address = <opaque blob for {'type': 'work', 'city': 'SF', 'street': 'Spear St'}>

L'entità verrà letta correttamente. Poiché le proprietà di questo tipo sempre non indicizzati, non puoi eseguire query per i valori degli indirizzi.

Nota: Un StructuredProperty con una proprietà nidificata (indipendentemente dal fatto che sia strutturata o meno) supporta un solo livello di proprietà ripetute. StructuredProperty può essere ripetuto oppure la proprietà nidificata può essere ripetuta, ma non entrambe. Una soluzione alternativa consiste nell'utilizzare LocalStructuredProperty, che non ha questo vincolo (ma non consente query sui valori delle sue proprietà).

Proprietà calcolate

Le proprietà calcolate (ComputedProperty) sono Proprietà di sola lettura il cui valore è calcolato da altri valori di proprietà da una funzione fornita dall'applicazione. Tieni presente che una proprietà calcolata supporta solo supportati dalle proprietà generiche. Il valore calcolato viene scritto Datastore in modo che sia possibile eseguire query e visualizzarli in visualizzatore, ma il valore memorizzato viene ignorato quando l'entità viene letta da Datastore; il valore viene ricalcolato chiamando il metodo ogni volta che viene richiesto il valore. Ad esempio:

class SomeEntity(ndb.Model):
    name = ndb.StringProperty()
    name_lower = ndb.ComputedProperty(lambda self: self.name.lower())
...
entity = SomeEntity(name='Nick')
entity.put()

Viene archiviata un'entità con i seguenti valori delle proprietà:

assert entity.name == 'Nick'
assert entity.name_lower == 'nick'

Se cambiamo il nome in "Nickie" e chiedi il valore name_lower, restituisce "nickie":

entity.name = 'Nick'
assert entity.name_lower == 'nick'
entity.name = 'Nickie'
assert entity.name_lower == 'nickie'

Nota: Utilizza ComputedProperty se l'applicazione query per il valore calcolato. Se vuoi solo per utilizzare la versione derivata nel codice Python, definisci un metodo regolare o utilizzare la tecnologia @property integrata di Python.

Nota: Se crei un modello senza una chiave specificata manualmente e invece ti affidi a Datastore per genera automaticamente l'ID dell'entità, poi la prima put() di un ComputedProperty non sarà in grado di leggere il campo ID perché il campo viene calcolato prima della generazione dell'ID. Se hai bisogno di un elemento ComputedProperty che utilizza l'ID dell'entità, puoi utilizzare il metodo allocate_ids per generare un ID e una chiave con cui creare l'entità, in modo che ComputedProperty potrà fare riferimento a quell'ID sulla prima funzione put() dell'entità.

Proprietà dei messaggi RPC del protocollo Google

La libreria Google Protocol RPC utilizza Message oggetti per i dati strutturati; possono rappresentare richieste, risposte RPC o altro. NDB fornisce un'API per l'archiviazione Gli oggetti RPC Message del protocollo Google come proprietà delle entità. Supponi di definire una sottoclasse Message:

from protorpc import messages
...
class Note(messages.Message):
    text = messages.StringField(1, required=True)
    when = messages.IntegerField(2)

Puoi archiviare Note oggetti in Datastore come entità dei valori delle proprietà usando l'API msgprop di NDB.

from google.appengine.ext import ndb
from google.appengine.ext.ndb import msgprop
...
class NoteStore(ndb.Model):
    note = msgprop.MessageProperty(Note, indexed_fields=['when'])
    name = ndb.StringProperty()
...
my_note = Note(text='Excellent note', when=50)

ns = NoteStore(note=my_note, name='excellent')
key = ns.put()

new_notes = NoteStore.query(NoteStore.note.when >= 10).fetch()

Se vuoi eseguire una query per i nomi dei campi, questi devono essere indicizzati. Puoi specificare un elenco di nomi di campi che verranno indicizzati con il parametro indexed_fields su MessageProperty.

MessageProperty supporta molti, ma non tutti, Opzioni proprietà. Supporta:

  • name
  • repeated
  • required
  • default
  • choices
  • validator
  • verbose_name

Le proprietà dei messaggi non supportano l'opzione della proprietà indexed. non puoi indicizzare Message valori. (puoi indicizzare campi di un messaggio come descritto sopra.

Anche i messaggi nidificati (con MessageField) funzionano:

class Notebook(messages.Message):
    notes = messages.MessageField(Note, 1, repeated=True)
...
class SignedStorableNotebook(ndb.Model):
    author = ndb.StringProperty()
    nb = msgprop.MessageProperty(
        Notebook, indexed_fields=['notes.text', 'notes.when'])

MessageProperty ha un'opzione per la proprietà speciale, protocol, che specifica come viene visualizzato l'oggetto del messaggio serializzato in Datastore. La i valori sono nomi di protocollo utilizzati da protorpc.remote.Protocols . I nomi dei protocolli supportati sono protobuf e protojson; il valore predefinito è protobuf.

msgprop definisce anche EnumProperty, una proprietà che può essere utilizzato per archiviare un protorpc.messages.Enum in un'entità. Esempio:

class Color(messages.Enum):
    RED = 620
    GREEN = 495
    BLUE = 450
...
class Part(ndb.Model):
    name = ndb.StringProperty()
    color = msgprop.EnumProperty(Color, required=True)
...
p1 = Part(name='foo', color=Color.RED)
print p1.color  # prints "RED"

EnumProperty memorizza il valore come numero intero, di fatto, EnumProperty è una sottoclasse di IntegerProperty. Ciò implica che puoi rinominare i valori enum senza dover modificare entità già archiviate, ma non è possibile rinumerarle.

EnumProperty supporta le seguenti opzioni proprietà:

  • name
  • indexed
  • repeated
  • required
  • default
  • choices
  • validator
  • verbose_name

Informazioni sui modelli di entità NDB

Un modello di entità NDB può definire le proprietà. Le proprietà delle entità sono un po' come i membri dei dati delle classi Python, un modo strutturato di conservare i dati; sono anche un po' come campi in una lo schema del database.

Un'applicazione tipica definisce un modello dei dati definendo una classe eredita da Model con alcuni attributi delle classi della proprietà. Ad esempio,


from google.appengine.ext import ndb
...
class Account(ndb.Model):
    username = ndb.StringProperty()
    userid = ndb.IntegerProperty()
    email = ndb.StringProperty()

Qui, username, userid e email sono proprietà di Account.

Esistono molti altri tipi di proprietà. Alcuni sono utili per rappresentare date e orari e sono comodi di aggiornamento automatico delle funzionalità.

Un'applicazione può regolare il comportamento di una proprietà specificando opzioni disponibili sulla proprietà: possono facilitare convalida, imposta i valori predefiniti o modifica l'indicizzazione delle query.

Un modello può avere proprietà più complesse. Le proprietà ripetute sono simili a un elenco. Le proprietà strutturate sono simili a quelle di un oggetto. Le proprietà calcolate di sola lettura vengono definite tramite le funzioni; e questo rende è facile definire una proprietà in termini di una o più altre proprietà. I modelli Expando possono e definire le proprietà in modo dinamico.