O Datastore fornece acesso programático a alguns de seus metadados para oferecer suporte à metaprogramação, implementar funções administrativas de back-end, simplificar o armazenamento em cache consistente e finalidades semelhantes. É possível usá-lo, por exemplo, para criar um visualizador personalizado do Datastore para seu aplicativo. Nos metadados disponíveis, há informações sobre grupos de entidades, namespaces, tipos de entidade e propriedades utilizadas pelo aplicativo, além de representações de cada propriedade.
O Painel do Datastore, no console do Google Cloud, também fornece alguns metadados sobre seu aplicativo, mas os dados exibidos nele diferem, em alguns aspectos importantes, dos retornados por essas funções.
- Atualização. A leitura de metadados pela API fornece dados atuais, enquanto os dados do painel são atualizados somente uma vez por dia.
- Conteúdo. Alguns metadados no painel não estão disponíveis através das APIs e vice-versa.
- Velocidade. Consultas e gets de metadados são faturados da mesma maneira que consultas e gets do Datastore. As consultas de metadados que buscam informações sobre namespaces, tipos e propriedades geralmente demoram a ser executadas. Como regra geral, uma consulta de metadados que retorna N entidades costuma levar mais ou menos o mesmo tempo que consultas N comuns, cada uma retornando uma única entidade. Além disso, as consultas de representação de propriedade, que são de propriedade sem chave, são mais lentas do que as consultas de propriedade apenas de chaves. Os resultados de metadados do grupo de entidades são um pouco mais rápidos do que uma entidade normal.
Metadados do grupo de entidades
No Cloud Datastore é possível ter acesso à "versão" de um grupo de entidades, um número estritamente positivo que tem garantia de aumentar a cada alteração no grupo de entidades.
As versões de grupo de entidades são recebidas chamando get()
em uma pseudoentidade especial
que contém uma propriedade __version__
estritamente positiva. A chave da pseudoentidade
pode ser criada usando o
método Entities.createEntityGroupKey()
:
Comportamento legado
No comportamento legado da versão do grupo de entidades, a versão aumenta apenas em alterações no grupo de entidades. O comportamento legado dos metadados do grupo de entidades poderia ser usado, por exemplo, para manter um cache consistente de uma consulta de ancestral complexa em um grupo de entidades.
Neste exemplo, armazenamos em cache os resultados da consulta (uma contagem de resultados correspondentes) e usamos o comportamento legado das versões do grupo de entidades para utilizar o valor em cache se ele for atual:
As entidades __entity_group__
podem não existir para grupos de entidades que nunca
foram gravados.
Consultas de metadados
A classe Java
Entities
,
definida no pacote
com.google.appengine.api.datastore
, fornece três tipos de entidades especiais que são reservadas para consultas de
metadados. Eles são indicados por constantes estáticas da classe Entities
:
Constante estática | Tipo de entidade |
---|---|
Entities.NAMESPACE_METADATA_KIND |
__namespace__ |
Entities.KIND_METADATA_KIND |
__kind__ |
Entities.PROPERTY_METADATA_KIND |
__property__ |
Esses tipos não entrarão em conflito com outros de nomes iguais que já podem existir no aplicativo. Ao consultar esses tipos especiais, você pode recuperar entidades que contenham os metadados desejados.
As entidades retornadas por consultas de metadados são geradas dinamicamente, com base no
estado atual do Datastore. Embora seja possível criar objetos
Entity
locais dos tipos __namespace__
, __kind__
ou
__property__
, qualquer
tentativa de armazená-los no Datastore falhará
com um
IllegalArgumentException
.
A maneira mais fácil de enviar consultas de metadados é com a API Datastore de baixo nível. O exemplo a seguir grava os nomes de todos os namespaces em um aplicativo:
Consultas de namespace
Se o aplicativo opta pela API Namespaces, é possível utilizar uma consulta de namespace para encontrar todos os namespaces usados nas entidades do aplicativo. Isso permite que você execute atividades, como funções administrativas, em vários namespaces.
As consultas de namespace retornam entidades do tipo especial __namespace__
, cujo nome
de chave é o nome de um namespace. Uma exceção é o namespace padrão
designado pela string vazia ""
: como a string vazia não é um nome de chave válido,
esse namespace é identificado pelo ID numérico 1
. As consultas desse
tipo são compatíveis apenas com a filtragem de intervalos na pseudopropriedade especial
__key__
, cujo valor é a chave da entidade. Os resultados podem ser classificados por
valor __key__
crescente (mas não decrescente). Como as entidades __namespace__
não têm propriedades, as consultas apenas de chaves e sem chave retornam as mesmas
informações.
O exemplo a seguir retorna uma lista de namespaces de um aplicativo no intervalo
entre dois nomes especificados, start
e end
:
Consultas de tipo
Consultas de tipo retornam entidades do tipo __kind__
, cujo nome de chave é o nome de
um tipo de entidade. As consultas desse tipo são implicitamente restritas ao namespace atual
e são compatíveis apenas com a filtragem para intervalos acima da
pseudopropriedade __key__
. Os resultados podem ser classificados por valor __key__
crescente
(mas não decrescente). Como as entidades __kind__
não têm propriedades, as consultas apenas
de chave e sem chave retornam as mesmas informações.
O exemplo a seguir imprime todos os tipos com nomes que começam com uma letra minúscula:
Consultas de propriedade
As consultas de propriedade retornam entidades do tipo __property__
que denotam as
propriedades associadas a um tipo de entidade. A
entidade que representa a propriedade P do tipo K é criada da seguinte forma:
- A chave da entidade tem o tipo
__property__
e o nome de chave P. - A chave da entidade pai tem o tipo
__kind__
e o nome da chave K.
O comportamento de uma consulta de propriedade depende do fato de ela ser uma consulta apenas de chaves ou apenas sem chave (representação de propriedade), conforme detalhado nas subseções a seguir.
Consultas de propriedade: somente com chaves
As consultas de propriedade somente com chaves retornam uma chave para cada propriedade indexada de um tipo de entidade especificado. As propriedades não indexadas não estão incluídas. O exemplo abaixo imprime os nomes de todos os tipos de entidade do aplicativo, bem como as propriedades associadas com cada um deles:
As consultas desse tipo são restritas implicitamente ao namespace atual e
à filtragem de suporte apenas para intervalos na pseudopropriedade __key__
, em que as
chaves denotam entidades __kind__
ou __property__
. Os resultados podem ser
classificados por valor __key__
crescente (mas não decrescente). A filtragem é aplicada
a pares de propriedade-tipo, classificados primeiro por tipo e depois por propriedade.
Por exemplo, suponha que você tenha uma entidade com estas propriedades:
- tipo
Account
com as propriedadesbalance
company
- tipo
Employee
com as propriedadesname
ssn
- tipo
Invoice
com as propriedadesdate
amount
- tipo
Manager
com as propriedadesname
title
- tipo
Product
com as propriedadesdescription
price
A consulta para retornar os dados da propriedade tem esta aparência:
A consulta acima apresenta o seguinte resultado:
Employee: ssn
Invoice: date
Invoice: amount
Manager: name
Os resultados não incluem a propriedade name
do tipo Employee
e a propriedade title
do tipo Manager
, nem quaisquer propriedades dos tipos
Account
e Product
, porque estão fora do intervalo especificado para a
consulta.
As consultas de propriedade também são compatíveis com a filtragem de ancestrais em uma chave __kind__
ou
__property__
para limitar os resultados da consulta a um único tipo ou propriedade. Você
pode usar isso, por exemplo, para ver as propriedades associadas a um determinado
tipo de entidade, como no exemplo a seguir:
Consultas de propriedade: somente sem chaves (representação de propriedade)
As consultas de propriedade somente sem chaves, conhecidas como consultas de representação de propriedade, retornam mais informações sobre as representações usadas por cada par de propriedade-tipo. As propriedades não indexadas não estão incluídas. A entidade retornada para a propriedade
P do tipo K tem a mesma chave de uma
consulta apenas de chaves,
junto com uma propriedade property_representation
adicional que retorna as
representações da propriedade. O valor dessa propriedade é uma instância da classe
java.util.Collection<String>
que contém uma string para cada representação da
propriedade P encontrada em qualquer entidade do tipo K.
Representações e classes de propriedades não são iguais. Várias classes de propriedades podem ser mapeadas para a mesma representação. Por exemplo,
java.lang.String
e
com.google.appengine.api.datastore.PhoneNumber
usam a representação STRING
.
Veja na tabela a seguir o mapeamento das classes de propriedades para as respectivas representações:
Classe de propriedade | Representação |
---|---|
java.lang.Byte |
INT64 |
java.lang.Short |
INT64 |
java.lang.Integer |
INT64 |
java.lang.Long |
INT64 |
java.lang.Float |
DOUBLE |
java.lang.Double |
DOUBLE |
java.lang.Boolean |
BOOLEAN |
java.lang.String |
STRING |
com.google.appengine.api.datastore.ShortBlob |
STRING |
java.util.Date |
INT64 |
com.google.appengine.api.datastore.GeoPt |
POINT |
com.google.appengine.api.datastore.PostalAddress |
STRING |
com.google.appengine.api.datastore.PhoneNumber |
STRING |
com.google.appengine.api.datastore.Email |
STRING |
com.google.appengine.api.users.User |
USER |
com.google.appengine.api.datastore.IMHandle |
STRING |
com.google.appengine.api.datastore.Link |
STRING |
com.google.appengine.api.datastore.Category |
STRING |
com.google.appengine.api.datastore.Rating |
INT64 |
com.google.appengine.api.datastore.Key |
REFERENCE |
com.google.appengine.api.blobstore.BlobKey |
STRING |
java.util.Collection<T> |
Representação de T |
O exemplo a seguir encontra todas as representações de uma propriedade especificada para um determinado tipo de entidade: