A biblioteca cliente NDB do Google Datastore permite que as apps Python do App Engine se liguem ao Datastore. A biblioteca de cliente NDB baseia-se na biblioteca DB Datastore mais antiga e adiciona as seguintes funcionalidades da loja de dados:
- A classe
StructuredProperty
, que permite que as entidades tenham uma estrutura aninhada. - Colocação em cache automática integrada, que normalmente oferece leituras rápidas e económicas através de uma cache no contexto e do Memcache.
- Suporta APIs assíncronas para ações simultâneas, além de APIs síncronas.
Esta página apresenta uma introdução e uma vista geral da biblioteca de cliente NDB do App Engine. Para obter informações sobre como migrar para o Cloud NDB, que suporta o Python 3, consulte o artigo Migrar para o Cloud NDB.
Definir entidades, chaves e propriedades
O Datastore armazena objetos de dados, denominados entidades. Uma entidade tem uma ou mais propriedades, valores denominados de um dos vários tipos de dados suportados. Por exemplo, uma propriedade pode ser uma string, um número inteiro ou uma referência a outra entidade.
Cada entidade é identificada por uma chave, um identificador exclusivo no arquivo de dados da aplicação. A chave pode ter um elemento principal, outra chave. Este principal pode ter um principal, e assim sucessivamente. No topo desta "cadeia" de principais encontra-se uma chave sem principal, denominada raiz.
As entidades cujas chaves têm a mesma raiz formam um grupo de entidades ou um grupo. Se as entidades estiverem em grupos diferentes, as alterações a essas entidades podem, por vezes, parecer ocorrer "fora de ordem". Se as entidades não estiverem relacionadas na semântica da sua aplicação, não há problema. No entanto, se as alterações de algumas entidades tiverem de ser consistentes, a sua aplicação deve torná-las parte do mesmo grupo quando as criar.
O diagrama de relação entre entidades e o exemplo de código seguintes mostram como um Guestbook
pode ter vários Greetings
, cada um com propriedades content
e date
.
Esta relação é implementada no exemplo de código abaixo.
Usar modelos para armazenar dados
Um modelo é uma classe que descreve um tipo de entidade, incluindo os tipos e a configuração das respetivas propriedades. É aproximadamente análogo a uma tabela em SQL. Pode criar uma entidade chamando o construtor da classe do modelo e, em seguida, armazená-la chamando o método put()
.
Este exemplo de código define a classe do modelo Greeting
. Cada entidade Greeting
tem duas propriedades: o conteúdo de texto da saudação e a data em que a saudação foi criada.
Para criar e armazenar uma nova saudação, a aplicação cria um novo objeto Greeting
e chama o respetivo método put()
.
Para garantir que as saudações num livro de visitas não aparecem "desordenadas", a aplicação define uma chave principal quando cria um novo Greeting
.
Assim, a nova saudação vai estar no mesmo grupo de entidades que outras saudações no mesmo livro de visitas. A aplicação usa este facto quando faz uma consulta: usa uma consulta de antepassados.
Consultas e índices
Uma aplicação pode consultar para encontrar entidades que correspondam a alguns filtros.
Uma consulta NDB típica filtra entidades por tipo. Neste exemplo, query_book
gera uma consulta que devolve Greeting
entidades. Uma consulta também pode especificar filtros em valores e chaves de propriedades de entidades.
Tal como neste exemplo, uma consulta pode especificar um antecessor, encontrando apenas entidades que "pertencem a" algum antecessor. Uma consulta pode especificar a ordem de ordenação. Se uma determinada entidade tiver, pelo menos, um valor (possivelmente nulo) para cada propriedade nos filtros e nas ordens de ordenação, e todos os critérios de filtro forem cumpridos pelos valores das propriedades, essa entidade é devolvida como resultado.
Todas as consultas usam um índice, uma tabela que contém os resultados da consulta na ordem pretendida. O Datastore subjacente mantém automaticamente índices simples (índices que usam apenas uma propriedade).
Define os respetivos índices complexos num ficheiro de configuração, index.yaml
. O servidor Web de desenvolvimento adiciona automaticamente sugestões a este ficheiro quando encontra consultas que ainda não têm índices configurados.
Pode ajustar os índices manualmente editando o ficheiro antes de carregar a aplicação. Pode atualizar os índices separadamente do carregamento da aplicação executando gcloud app deploy index.yaml
.
Se o seu arquivo de dados tiver muitas entidades, demorará muito tempo a criar um novo índice para as mesmas. Neste caso, é aconselhável atualizar as definições de índice antes de carregar código que use o novo índice. Pode usar a consola de administração
para saber quando os índices terminaram de ser criados.
Este mecanismo de indexação suporta uma vasta gama de consultas e é adequado para a maioria das aplicações. No entanto, não suporta alguns tipos de consultas comuns noutras tecnologias de bases de dados. Em particular, as junções não são suportadas.
Compreender as escritas da NDB: confirmar, invalidar a cache e aplicar
O NDB escreve dados em passos:
- Na fase de confirmação, o serviço Datastore subjacente regista as alterações.
- O NDB invalida as respetivas caches da entidade/entidades afetadas. Assim, as leituras futuras vão ler (e colocar em cache) o Datastore subjacente em vez de ler valores desatualizados da cache.
- Por fim, talvez segundos depois, o Datastore subjacente aplica a alteração. Torna a alteração visível para consultas globais e, eventualmente, leituras consistentes.
A função NDB que escreve os dados (por exemplo, put()
) devolve após a invalidação da cache; a fase de aplicação ocorre de forma assíncrona.
Se ocorrer uma falha durante a fase de confirmação, são feitas novas tentativas automáticas, mas, se as falhas continuarem, a sua aplicação recebe uma exceção. Se a fase Commit for bem-sucedida, mas a fase Apply falhar, a fase Apply é avançada até à conclusão quando ocorre uma das seguintes situações:
- As "limpezas" periódicas do Datastore verificam se existem tarefas de confirmação não concluídas e aplicam-nas.
- A próxima gravação, transação ou leitura fortemente consistente no grupo de entidades afetado faz com que as alterações ainda não aplicadas sejam aplicadas antes da leitura, da gravação ou da transação.
Este comportamento afeta a forma e o momento em que os dados ficam visíveis para a sua aplicação. A alteração pode não ser aplicada completamente ao Datastore subjacente alguns centenas de milissegundos após a função NDB ser devolvida. Uma consulta não de antepassado executada enquanto uma alteração está a ser aplicada pode ver um estado inconsistente, ou seja, parte, mas não toda a alteração.
Transações e dados de colocação em cache
A biblioteca cliente NDB pode agrupar várias operações numa única transação. A transação não pode ser bem-sucedida, a menos que todas as operações na transação sejam bem-sucedidas. Se alguma das operações falhar, a transação é revertida automaticamente. Isto é particularmente útil para aplicações Web distribuídas, em que vários utilizadores podem estar a aceder ou a manipular os mesmos dados ao mesmo tempo.
O NDB usa o Memcache como um serviço de cache para "hot spots" nos dados. Se a aplicação ler algumas entidades com frequência, o NDB pode lê-las rapidamente a partir da cache.
Usar o Django com o NDB
Para usar o NDB com a framework Web Django, adicione google.appengine.ext.ndb.django_middleware.NdbDjangoMiddleware
à entrada MIDDLEWARE_CLASSES
no seu ficheiro settings.py
do Django. É melhor inseri-lo antes de quaisquer outras classes de middleware, porque algum outro middleware pode fazer chamadas de armazenamento de dados e estas não são processadas corretamente se esse middleware for invocado antes deste middleware. Pode saber mais acerca do
middleware Django.
What's Next?
Saiba mais sobre:
- Criar entidades no NDB.
- Como as transações são processadas no Datastore.
- Como criar e formatar uma consulta com a biblioteca de cliente NDB.
- Colocar dados em cache com o NDB e a infraestrutura Memcache subjacente.
- Administrar e gerir dados armazenados no Armazenamento de Dados.