Os cursores de consultas permitem que uma aplicação obtenha os resultados de uma consulta em lotes convenientes e são recomendados em vez de usar deslocamentos de números inteiros para paginação. Consulte o artigo Consultas para mais informações sobre a estruturação de consultas para a sua app.
Cursores de consulta
Os cursores de consulta permitem que uma aplicação obtenha os resultados de uma consulta em lotes convenientes sem incorrer na sobrecarga de uma compensação de consulta. Após realizar uma operação de obtenção, a aplicação pode obter um cursor, que é uma string codificada em base64 opaca que marca a posição do índice do último resultado obtido. A aplicação pode guardar esta string, por exemplo, no Datastore, no Memcache, num payload de tarefas da fila de tarefas ou incorporada numa página Web como um parâmetro HTTP GET
ou POST
e, em seguida, pode usar o cursor como ponto de partida para uma operação de obtenção subsequente para obter o lote seguinte de resultados a partir do ponto em que a obtenção anterior terminou. Uma obtenção também pode especificar um cursor final para limitar a extensão do conjunto de resultados devolvido.
Compensações versus cursores
Embora o Datastore suporte deslocamentos de números inteiros, deve evitar usá-los. Em alternativa, use cursores. A utilização de um desvio apenas evita devolver as entidades ignoradas à sua aplicação, mas estas entidades continuam a ser obtidas internamente. As entidades ignoradas afetam a latência da consulta e a sua aplicação é faturada pelas operações de leitura necessárias para as obter. A utilização de cursores em vez de deslocamentos permite-lhe evitar todos estes custos.
Exemplo de cursor de consulta
Na API de baixo nível, a aplicação pode usar cursores através das interfaces QueryResultList
, QueryResultIterable
e QueryResultIterator
, que são devolvidas pelos métodos PreparedQuery
, asQueryResultList()
, asQueryResultIterable()
e asQueryResultIterator()
, respetivamente. Cada um destes objetos de resultado fornece um método getCursor()
, que, por sua vez, devolve um objeto Cursor
. A aplicação pode obter uma string segura para a Web que representa o cursor chamando o método toWebSafeString()
do objeto Cursor
e pode usar posteriormente o método estático Cursor.fromWebSafeString()
para reconstituir o cursor a partir da string.
O exemplo seguinte demonstra a utilização de cursores para paginação:
Limitações dos cursores
Os cursores estão sujeitos às seguintes limitações:
- Um cursor só pode ser usado pela mesma aplicação que executou a consulta original e apenas para continuar a mesma consulta. Para usar o cursor numa operação de obtenção subsequente, tem de reconstituir exatamente a consulta original, incluindo o mesmo tipo de entidade, filtro de antepassados, filtros de propriedades e ordens de ordenação. Não é possível obter resultados através de um cursor sem configurar a mesma consulta a partir da qual foi originalmente gerado.
- Uma vez que os operadores
NOT_EQUAL
eIN
são implementados com várias consultas, as consultas que os usam não suportam cursores, nem consultas compostas criadas com o métodoCompositeFilterOperator.or
. - Os cursores nem sempre funcionam como esperado com uma consulta que usa um filtro de desigualdade ou uma ordem de ordenação numa propriedade com vários valores. A lógica de remoção de duplicados para essas propriedades com vários valores não persiste entre obtenções, o que pode fazer com que o mesmo resultado seja devolvido mais do que uma vez.
- Os novos lançamentos do App Engine podem alterar os detalhes de implementação interna,
invalidando os cursores que dependem deles. Se uma aplicação tentar usar um cursor que já não é válido, o Datastore gera um erro
IllegalArgumentException
(API de baixo nível),JDOFatalUserException
(JDO) ouPersistenceException
(JPA).
Cursores e atualizações de dados
A posição do cursor é definida como a localização na lista de resultados após o último resultado devolvido. Um cursor não é uma posição relativa na lista (não é um desvio); é um marcador para o qual o Datastore pode saltar quando inicia uma análise de índice para resultados. Se os resultados de uma consulta mudarem entre utilizações de um cursor, a consulta apenas nota as alterações que ocorrem nos resultados após o cursor. Se aparecer um novo resultado antes da posição do cursor para a consulta, não é devolvido quando os resultados após o cursor são obtidos. Da mesma forma, se uma entidade deixar de ser um resultado para uma consulta, mas tiver aparecido antes do cursor, os resultados que aparecem depois do cursor não mudam. Se o último resultado devolvido for removido do conjunto de resultados, o cursor continua a saber como localizar o resultado seguinte.
Ao obter resultados de consultas, pode usar um cursor de início e um cursor de fim para devolver um grupo contínuo de resultados do Datastore. Quando usa um cursor de início e fim para obter os resultados, não tem a garantia de que o tamanho dos resultados seja o mesmo que quando gerou os cursores. As entidades podem ser adicionadas ou eliminadas do Datastore entre o momento em que os cursores são gerados e o momento em que são usados numa consulta.
O que se segue?
- Saiba como especificar o que uma consulta devolve e controlar ainda mais os resultados da consulta.
- Conheça as restrições comuns para consultas no Datastore.
- Compreenda a consistência dos dados e como a consistência dos dados funciona com diferentes tipos de consultas no Datastore.
- Aprenda a sintaxe e a estrutura básicas das consultas para o Datastore.