Os cursores de consulta permitem a recuperação, por parte de um aplicativo, dos resultados de uma consulta em lotes convenientes, sendo o uso recomendado em deslocamentos inteiros para paginação. Saiba mais sobre como estruturar consultas para o aplicativo em Consultas.
Cursores de consulta
Os cursores de consulta permitem a recuperação, por parte de um aplicativo, dos resultados de uma consulta em lotes convenientes, evitando a sobrecarga do deslocamento dessa consulta. Após executar uma
operação de recuperação, o aplicativo recebe um
cursor, que é uma string opaca codificada em base64 que marca a posição do índice do
último resultado recuperado. O aplicativo pode salvar essa string, por exemplo, no
Datastore, no Memcache, em um payload de tarefa do Task Queue ou incorporada em
uma página da Web como parâmetro HTTP GET
ou POST
. Depois, ele pode usar o cursor como
ponto de partida para uma operação de recuperação subsequente. Nesse caso, o lote seguinte
de resultados será conseguido a partir do ponto em que a recuperação anterior terminou. É possível que
uma recuperação também especifique um cursor de término para limitar a extensão do conjunto de resultados retornados.
Deslocamentos versus cursores
O Datastore é compatível com deslocamentos de números inteiros, mas é melhor evitá-los. Em vez disso, use cursores. O uso de um deslocamento evita apenas o retorno de entidades ignoradas ao aplicativo, mas é possível recuperá-las internamente. Na verdade, as entidades ignoradas afetam a latência da consulta. Além disso, o aplicativo será cobrado pelas operações de leitura necessárias para a recuperação dessas entidades. Use cursores em vez de deslocamentos para evitar todos esses custos.
Exemplo de cursor de consulta
Na API de nível inferior, o aplicativo pode usar cursores por meio das interfaces
QueryResultList
,
QueryResultIterable
e
QueryResultIterator
,
que são retornadas pelos métodos
PreparedQuery
asQueryResultList()
,
asQueryResultIterable()
,
e asQueryResultIterator()
,
respectivamente. Cada um desses objetos de resultado fornece um
método
getCursor()
, que, por sua vez, retorna um objeto
Cursor
. Para receber uma string segura para Web que representa o cursor, o aplicativo pode
chamar o método toWebSafeString()
do objeto Cursor
e usar o método estático
Cursor.fromWebSafeString()
para reconstituir o cursor a partir da string.
O exemplo a seguir demonstra o uso de cursores para paginação:
Limitações dos cursores
Os cursores estão sujeitos às seguintes limitações:
- Um cursor é usado somente pelo mesmo projeto que executou a consulta original e para continuar a mesma consulta. Para usar o cursor em uma operação de recuperação posterior, reconstitua na íntegra a consulta original, incluindo o mesmo tipo de entidade, filtro de ancestrais e de propriedades e ordens de classificação. Não é possível recuperar resultados usando um cursor sem configurar a mesma consulta que o gerou.
- Como os operadores
NOT_EQUAL
eIN
são implementados com várias consultas, as que os utilizam não são compatíveis com cursores ou com as consultas compostas criadas com o métodoCompositeFilterOperator.or
. - Cursores nem sempre funcionam como esperado em uma consulta que usa um filtro de desigualdade ou uma ordem de classificação em uma propriedade com valores múltiplos. A lógica de eliminar a duplicação para essas propriedades não se mantém entre as recuperações. Assim, é possível que o mesmo resultado seja retornado mais de uma vez.
- Novas versões do App Engine podem alterar os detalhes de implementação internos,
invalidando cursores que dependem deles. Se um aplicativo tentar usar um
cursor que não é mais válido, o Datastore
apontará
IllegalArgumentException
(API de baixo nível),JDOFatalUserException
(JDO) ouPersistenceException
(JPA).
Cursores e atualizações de dados
A posição do cursor é definida como o local na lista de resultados após o último resultado retornado. Um cursor não é uma posição relativa na lista, não é um deslocamento, e sim um marcador para o qual o Datastore pode pular ao iniciar uma varredura de índice em busca de resultados. Caso os resultados de uma consulta sofram alteração entre os usos de um cursor, ela refletirá apenas as alterações ocorridas nos resultados após o cursor. Se na consulta aparecer um novo resultado antes da posição do cursor, ele não será retornado quando forem recuperados os resultados após o cursor. Da mesma forma, caso uma entidade não seja mais o resultado de uma consulta, mesmo tendo aparecido antes do cursor, os resultados após o cursor não serão alterados. Caso o último resultado retornado seja removido do conjunto de resultados, o cursor ainda saberá como localizar o próximo.
Ao recuperar os resultados da consulta, é possível usar um cursor inicial e um cursor final para retornar um grupo contínuo de resultados do Datastore. Usar um cursor de início e de término na recuperação de resultados não garante que o tamanho dos resultados seja o mesmo de quando os cursores foram gerados. As entidades podem ser adicionadas ou excluídas do Datastore entre o momento em que os cursores são gerados e o momento em que são usados em uma consulta.
A seguir
- Saiba como especificar qual é o retorno de uma consulta e outros resultados de consulta de controle.
- Conheça as restrições comuns para consultas no Datastore.
- Entenda a consistência dos dados e como ela funciona com diferentes tipos de consultas no Datastore.
- Conheça a sintaxe básica e a estrutura das consultas do Datastore.