O Firestore no modo Datastore (Datastore) suporta uma variedade de tipos de dados para valores de propriedades. Estas incluem, entre outras:
- Números inteiros
- Números de vírgula flutuante
- Strings
- Datas
- Dados binários
Para ver uma lista completa de tipos, consulte Propriedades e tipos de valores.
Propriedades e tipos de valores
Os valores de dados associados a uma entidade consistem numa ou mais propriedades. Cada propriedade tem um nome e um ou mais valores. Uma propriedade pode ter valores de mais do que um tipo, e duas entidades podem ter valores de tipos diferentes para a mesma propriedade. As propriedades podem ser indexadas ou não indexadas (as consultas que ordenam ou filtram uma propriedade P ignoram as entidades em que P não está indexada). Uma entidade pode ter, no máximo, 20 000 propriedades indexadas.
São suportados os seguintes tipos de valores:
Quando uma consulta envolve uma propriedade com valores de tipos mistos, o Datastore usa uma ordenação determinística com base nas representações internas:
- Valores nulos
- Números de ponto fixo
- Números inteiros
- Datas e horas
- Valores booleanos
- Sequências de bytes
- String Unicode
- Chaves do Blobstore
- Números de vírgula flutuante
- Chaves do Datastore
Uma vez que as strings de texto longas e as strings de bytes longas não são indexadas, não têm uma ordenação definida.
Tipos de propriedades
O NDB suporta os seguintes tipos de propriedades:
Tipo de propriedade | Descrição |
---|---|
IntegerProperty | Número inteiro com sinal de 64 bits |
FloatProperty | Número de vírgula flutuante de precisão dupla |
BooleanProperty | Booleano |
StringProperty | String Unicode; até 1500 bytes, indexada |
TextProperty | String Unicode; comprimento ilimitado, não indexada |
BlobProperty | String de bytes não interpretada: se definir indexed=True , até 1500 bytes, indexada;se indexed for False (a predefinição), comprimento ilimitado, não indexada.Argumento de palavra-chave opcional: compressed .
|
DateTimeProperty
| Data e hora (consulte as Propriedades de data e hora) |
DateProperty
| Data (consulte as propriedades de data e hora) |
TimeProperty
| Hora (consulte as propriedades de data e hora) |
GeoPtProperty
| Localização geográfica. Este é um objeto ndb.GeoPt .
O objeto tem os atributos lat e lon , ambos flutuantes.
Pode construir um com dois números de vírgula flutuante, como
ndb.GeoPt(52.37, 4.88)
ou com uma string ndb.GeoPt("52.37, 4.88") .
(Na verdade, esta é a mesma classe que
db.GeoPt )
|
KeyProperty | Datastore key Argumento de palavra-chave opcional: kind=kind, para exigir que as chaves atribuídas a esta propriedade tenham sempre o tipo indicado. Pode ser uma string ou uma subclasse de modelo. |
BlobKeyProperty
| Chave do Blobstore Corresponde a BlobReferenceProperty na API db antiga, mas o valor da propriedade é um BlobKey em vez de um BlobInfo ; pode construir um BlobInfo a partir dele usando BlobInfo(blobkey)
|
UserProperty | Objeto do utilizador. |
StructuredProperty
| Inclui um tipo de modelo dentro de outro, por valor (consulte Propriedades estruturadas) |
LocalStructuredProperty
| Semelhante a StructuredProperty ,
mas a representação no disco é um blob opaco e não é indexada
(consulte Propriedades estruturadas).Argumento de palavra-chave opcional: compressed .
|
JsonProperty
| O valor é um objeto Python (como uma lista, um dicionário ou uma string)
que é serializável através do módulo json do Python;
o Datastore armazena
a serialização JSON como um blob. Não indexado por predefinição.Argumento de palavra-chave opcional: compressed .
|
PickleProperty
| O valor é um objeto Python (como uma lista, um dict ou uma string) que é serializável através do protocolo pickle do Python. O Datastore armazena a serialização pickle como um blob. Não indexado por predefinição. Argumento de palavra-chave opcional: compressed .
|
GenericProperty | Valor genérico Usado principalmente pela classe Expando , mas também pode ser usado explicitamente. O respetivo tipo pode ser qualquer um dos seguintes:
int , long ,
float , bool , str ,
unicode , datetime , Key ,
BlobKey , GeoPt , User ,
None .
|
ComputedProperty
| Valor calculado a partir de outras propriedades por uma função definida pelo utilizador. (Consulte Propriedades calculadas.) |
Algumas destas propriedades têm um argumento de palavra-chave opcional,
compressed
. Se a propriedade tiver
compressed=True
, os respetivos dados são comprimidos com gzip no disco.
Ocupa menos espaço, mas precisa de CPU para codificar/descofificar nas operações de escrita e leitura.
A compressão e a descompressão são "preguiçosas"; um valor de propriedade comprimido só é descomprimido na primeira vez que lhe acede. Se ler uma entidade que contenha um valor de propriedade comprimido e escrevê-lo novamente sem aceder à propriedade comprimida, esta não é descomprimida nem comprimida. A cache no contexto também participa neste esquema de carregamento diferido, mas o memcache armazena sempre o valor comprimido para propriedades comprimidas.
Devido ao tempo de CPU adicional necessário para a compressão, é normalmente melhor usar propriedades comprimidas apenas se os dados forem demasiado grandes para caber sem compressão. Lembre-se de que a compressão baseada em gzip não é normalmente eficaz para imagens e outros dados multimédia, uma vez que esses formatos já estão comprimidos através de um algoritmo de compressão específico de multimédia (por exemplo, JPEG para imagens).
Opções de propriedade
A maioria dos tipos de propriedades suporta alguns argumentos padrão. O primeiro é um argumento posicional opcional que especifica o nome do Datastore da propriedade. Pode usar esta opção para dar à propriedade um nome diferente no Datastore do que do ponto de vista da aplicação. Uma utilização comum desta funcionalidade é reduzir o espaço no Datastore, permitindo que o Datastore use nomes de propriedades abreviados enquanto o seu código usa nomes mais longos e significativos. Por exemplo,
Isto é particularmente útil para propriedades repetidas para as quais espera muitos valores por entidade.
Além disso, a maioria dos tipos de propriedades suporta os seguintes argumentos de palavras-chave:
Argumento | Tipo | Predefinição | Descrição |
---|---|---|---|
indexed | bool | Normalmente, True | Inclua a propriedade nos índices do Datastore; se for False , não é possível consultar os valores, mas as escritas são mais rápidas. Nem todos os tipos de propriedades suportam a indexação. A definição de indexed como True falha para estes.As propriedades não indexadas custam menos operações de escrita do que as propriedades indexadas. |
repeated | bool | False | O valor da propriedade é uma lista Python que contém valores do tipo subjacente (consulte Propriedades repetidas). Não é possível combinar com required=True nem default=True .
|
required | bool | False | A propriedade tem de ter um valor especificado. |
default | Tipo subjacente da propriedade | Nenhum | Valor predefinido da propriedade se não for especificado explicitamente nenhum valor. |
choices | Lista de valores do tipo subjacente | None | Lista opcional de valores permitidos. |
validator | Função | None | Função opcional para validar e, possivelmente, forçar o valor. Vai ser chamado com os argumentos
(prop, value) e deve devolver o valor (possivelmente forçado) ou gerar uma exceção. Chamar a função novamente
num valor convertido não deve modificar mais o valor.
(Por exemplo, devolver |
verbose_name | de string | None
| Etiqueta HTML opcional a usar em frameworks de formulários Web, como o jinja2. |
Propriedades repetidas
Qualquer propriedade com
repeated=True
torna-se uma propriedade repetida.
A propriedade recebe uma lista de valores do tipo subjacente,
em vez de um único valor.
Por exemplo, o valor de uma propriedade definida com
IntegerProperty(repeated=True)
é uma lista de números inteiros.
O Datastore pode ver vários valores para essa propriedade. É criado um registo de índice separado para cada valor. Isto afeta a semântica das consultas. Consulte o artigo Consultar propriedades repetidas para ver um exemplo.
Este exemplo usa uma propriedade repetida:
...
Isto cria uma entidade do Datastore com os seguintes conteúdos:
Quando consulta a propriedade tags
, esta entidade satisfaz uma consulta para 'python'
ou 'ruby'
.
Quando atualiza uma propriedade repetida, pode atribuir-lhe uma nova lista ou alterar a lista existente no local.
Quando atribui uma nova lista, os tipos dos itens da lista são validados imediatamente. Os tipos de itens inválidos
(por exemplo, atribuir [1, 2]
a art.tags
acima) geram uma exceção.
Quando altera a lista, a alteração não é validada imediatamente.
Em alternativa, o valor é validado quando escreve a entidade no Datastore.
O Datastore preserva a ordem dos itens da lista numa propriedade repetida, pelo que pode atribuir algum significado à respetiva ordenação.
Propriedades de data e hora
Estão disponíveis três tipos de propriedades para armazenar valores relacionados com datas e horas:
DateProperty
TimeProperty
DateTimeProperty
Estes assumem valores pertencentes às classes correspondentes
(date
, time
, datetime
)
do módulo datetime
padrão do Python.
O mais geral dos três é DateTimeProperty
, que denota uma data do calendário e uma hora do dia. Os outros são ocasionalmente úteis para fins especiais que requerem apenas uma data (como uma data de nascimento) ou apenas uma hora (como uma hora de reunião).
Por motivos técnicos, DateProperty
e TimeProperty
são subclasses de DateTimeProperty
,
mas não deve depender desta relação de herança
(e tenha em atenção que difere das relações de herança entre
as classes subjacentes definidas pelo próprio módulo datetime
).
Nota:
as horas do relógio do App Engine são sempre expressas em tempo universal
coordenado (UTC). Isto torna-se relevante se usar a data ou a hora atual (datetime.datetime.now()
) como um valor ou converter entre objetos datetime e datas/horas POSIX ou tuplos de tempo.
No entanto, não são armazenadas informações explícitas de fuso horário no Datastore. Por isso, se tiver cuidado, pode usá-las para representar horas locais em qualquer fuso horário, se usar a hora atual ou as conversões.
Cada uma destas propriedades tem duas opções de palavras-chave booleanas adicionais:
Opção | Descrição |
---|---|
auto_now_add
| Defina a propriedade para a data/hora atual quando a entidade for criada. Pode substituir manualmente esta propriedade. Quando a entidade é atualizada, a propriedade não é alterada. Para esse comportamento, use
auto_now .
|
auto_now
| Defina a propriedade para a data/hora atual quando a entidade é criada e sempre que é atualizada. |
Não é possível combinar estas opções com
repeated=True
.
Ambos têm como predefinição False
;
se ambos estiverem definidos como True
, auto_now
tem prioridade.
É possível substituir o valor de uma propriedade com
auto_now_add=True
,
mas não de uma com auto_now=True
.
O valor automático não é gerado até que a entidade seja escrita;
ou seja, estas opções não fornecem predefinições dinâmicas.
(Estes detalhes diferem da antiga API db.)
Nota:
Quando uma transação que escreve uma propriedade com
auto_now_add=True
falha e é tentada novamente mais tarde, reutiliza o mesmo valor de tempo da tentativa original, em vez de o atualizar para o momento da nova tentativa. Se a transação falhar permanentemente, o valor da propriedade continua definido na cópia da entidade na memória.
Propriedades estruturadas
Pode estruturar as propriedades de um modelo.
Por exemplo, pode definir uma classe de modelo Contact
que contenha uma lista de moradas, cada uma com uma estrutura interna.
As propriedades estruturadas (tipo StructuredProperty
) permitem-lhe fazê-lo. Por exemplo:
...
...
Isto cria uma única entidade do Datastore com as seguintes propriedades:
A leitura de uma entidade deste tipo reconstrói exatamente a entidade Contact
original.
Embora as instâncias Address
sejam definidas
com a mesma sintaxe que para as classes de modelos,
não são entidades completas.
Não têm as suas próprias chaves no Datastore.
Não podem ser obtidos independentemente da entidade Contact
à qual pertencem.
No entanto, uma aplicação pode consultar os valores dos respetivos campos individuais. Consulte a secção
Filtrar valores de propriedades estruturadas.
Tenha em atenção que address.type
, address.street
e address.city
são vistos como matrizes paralelas do ponto de vista do Datastore, mas a biblioteca NDB oculta este aspeto e cria a lista correspondente de instâncias Address
.
Pode especificar as opções de propriedade habituais para propriedades estruturadas (exceto indexed
). O nome do Datastore é o segundo argumento posicional neste caso (o primeiro é a classe de modelo usada para definir a subestrutura).
Quando não precisa de consultar as propriedades internas de uma subestrutura, pode usar uma propriedade estruturada local (LocalStructuredProperty
). Se substituir StructuredProperty
por
LocalStructuredProperty
no exemplo acima, o comportamento
do código Python é o mesmo, mas o Datastore vê apenas um blob opaco
para cada endereço. A entidade guido
criada no exemplo seria armazenada da seguinte forma:
name = "Guido"
address = <opaque blob for {'type': 'home', 'city': 'Amsterdam'}>
address = <opaque blob for {'type': 'work', 'city': 'SF',
'street': 'Spear St'}>
A entidade é lida corretamente. Uma vez que as propriedades deste tipo estão sempre não indexadas, não pode consultar valores de morada.
Nota:
Um StructuredProperty
com uma propriedade aninhada (estruturada ou não)
suporta apenas uma camada de propriedades repetidas. O StructuredProperty
pode ser repetido ou a propriedade aninhada pode ser repetida, mas não ambos. Uma solução alternativa é usar
LocalStructuredProperty
, que não tem esta restrição (mas não permite
consultas sobre os valores das respetivas propriedades).
Propriedades calculadas
As propriedades calculadas (ComputedProperty
) são propriedades de leitura
cujo valor é calculado a partir de outros valores de propriedades
por uma função fornecida pela aplicação. Tenha em atenção que uma propriedade calculada só suporta os tipos suportados por propriedades genéricas. O valor calculado é escrito no Datastore para que possa ser consultado e apresentado no visualizador do Datastore, mas o valor armazenado é ignorado quando a entidade é lida novamente a partir do Datastore. Em vez disso, o valor é recalculado chamando a função sempre que o valor é pedido. Por exemplo:
...
Isto armazena uma entidade com os seguintes valores de propriedades:
Se alterarmos o nome para "Nickie" e pedirmos o valor de
name_lower
, é devolvido "nickie":
Nota:
Use ComputedProperty
se a aplicação
consultar o valor calculado. Se apenas quiser usar a versão derivada no código Python, defina um método normal ou use a função integrada @property
do Python.
Nota:
se criar um modelo sem uma chave especificada manualmente e, em vez disso, confiar no Datastore para
gerar automaticamente o ID da entidade, na primeira put()
, um ComputedProperty
não vai conseguir ler o campo de ID, uma vez que o campo é calculado antes de o ID ser gerado.
Se precisar de um ComputedProperty
que use o ID da entidade, pode usar o método
allocate_ids
para gerar um ID e uma chave para criar a entidade, de modo que
o seu ComputedProperty
possa referenciar esse ID no primeiro put() da entidade.
Propriedades de mensagens RPC do protocolo Google
A biblioteca Google Protocol RPC usa objetos
Message
para dados estruturados. Estes podem representar pedidos RPC, respostas ou outras coisas. O NDB fornece uma API para armazenar objetos Message
Google Protocol RPC Message
como propriedades de entidades.
Suponhamos que define uma subclasse Message
:
...
Pode armazenar objetos Note
no Datastore como valores de propriedades de entidades usando a API msgprop
do NDB.
...
...
Se quiser consultar nomes de campos, estes têm de ser indexados.
Pode especificar uma lista de nomes de campos que vão ser indexados com o parâmetro indexed_fields
para MessageProperty
.
MessageProperty
suporta muitas, mas não todas, as
opções de propriedades. Suporta:
name
repeated
required
default
choices
validator
verbose_name
As propriedades de mensagens não suportam a opção de propriedade indexed
;
não pode indexar valores Message
. (Pode indexar campos de uma mensagem conforme descrito acima.)
As mensagens aninhadas (com MessageField
) também funcionam:
...
MessageProperty
tem uma opção de propriedade especial,
protocol
, que especifica como o objeto de mensagem é
serializado para o Datastore. Os valores são nomes de protocolos usados pela classe protorpc.remote.Protocols
. Os nomes dos protocolos suportados são protobuf
e protojson
. O protocolo predefinido é protobuf
.
msgprop
também define EnumProperty
, um tipo de propriedade que pode ser usado para armazenar um valor protorpc.messages.Enum
numa entidade. Exemplo:
...
...
EnumProperty
armazena o valor como um número inteiro. Na verdade, EnumProperty
é uma subclasse de IntegerProperty
.
Isto implica que pode mudar o nome dos valores de enumeração sem ter de modificar as entidades já armazenadas, mas não pode reenumerá-los.
A EnumProperty suporta as seguintes opções de propriedade:
name
indexed
repeated
required
default
choices
validator
verbose_name
Acerca dos modelos de entidades NDB
Um modelo de entidade NDB pode definir propriedades. As propriedades das entidades são um pouco semelhantes aos membros de dados das classes Python, uma forma estruturada de armazenar dados. Também são um pouco semelhantes aos campos num esquema de base de dados.
Uma aplicação típica define um modelo de dados definindo uma classe que
herda de Model
com alguns atributos de classe de propriedade.
Por exemplo,
...
Aqui, username
, userid
e
email
são propriedades de Account
.
Existem vários outros tipos de propriedades. Alguns são úteis para representar datas e horas e têm funcionalidades de atualização automática convenientes.
Uma aplicação pode ajustar o comportamento de uma propriedade especificando opções na propriedade. Estas podem facilitar a validação, definir predefinições ou alterar a indexação de consultas.
Um modelo pode ter propriedades mais complexas. As propriedades repetidas são semelhantes a listas. As propriedades estruturadas são semelhantes a objetos. As propriedades calculadas só de leitura são definidas através de funções, o que facilita a definição de uma propriedade em termos de uma ou mais outras propriedades. Os modelos Expando podem definir propriedades dinamicamente.