I cursori di query consentono a un'applicazione di recuperare i risultati di una query in comodi batch e sono consigliati rispetto all'utilizzo di offset interi per la paginazione. Per ulteriori informazioni sulla strutturazione delle query per la tua app, consulta Query.
Cursori di query
I cursori di query consentono a un'applicazione di recuperare i risultati di una query in comodi batch senza l'overhead di un offset di query. Dopo aver eseguito un'operazione di recupero, l'applicazione può ottenere un cursore, ovvero una stringa opaca codificata in base64 che indica la posizione dell'indice dell'ultimo risultato recuperato. L'applicazione può salvare questa stringa, ad esempio in Datastore, in Memcache, nel payload di un'attività della coda di lavoro o incorporata in una pagina web come parametro HTTP GET
o POST
e può quindi utilizzare il cursore come punto di partenza per un'operazione di recupero successiva per ottenere il batch successivo di risultati dal punto in cui è terminato il recupero precedente. Un recupero può anche specificare un cursore di fine per limitare l'ambito del set di risultati restituito.
Differenza tra offset e cursori
Anche se Datastore supporta gli offset interi, dovresti evitare di utilizzarli. Utilizza invece i cursori. L'utilizzo di un offset evita solo di restituire le entità saltate alla tua applicazione, ma queste entità vengono comunque recuperate internamente. Le entità ignorate influiscono sulla latenza della query e alla tua applicazione vengono addebitate le operazioni di lettura necessarie per recuperarle. L'utilizzo di cursori anziché offset ti consente di evitare tutti questi costi.
Esempio di cursore di query
Nell'API di basso livello, l'applicazione può utilizzare i cursori tramite le interfacce
QueryResultList
,
QueryResultIterable
e
QueryResultIterator
,
rispettivamente restituite dai metodi
PreparedQuery
asQueryResultList()
,
asQueryResultIterable()
e asQueryResultIterator()
. Ciascuno di questi oggetti risultato fornisce un metodo getCursor()
, che a sua volta restituisce un oggetto Cursor
. L'applicazione può ottenere una stringa sicura per il web che rappresenta il cursore chiamando il metodo toWebSafeString()
dell'oggetto Cursor
e in un secondo momento può utilizzare il metodo statico Cursor.fromWebSafeString()
per ricostituire il cursore dalla stringa.
L'esempio seguente mostra l'utilizzo dei cursori per la paginazione:
Limitazioni dei cursori
I cursori sono soggetti alle seguenti limitazioni:
- Un cursore può essere utilizzato solo dalla stessa applicazione che ha eseguito la query originale e solo per continuare la stessa query. Per utilizzare il cursore in un'operazione di recupero successiva, devi ricostituire esattamente la query originale, inclusi lo stesso tipo di entità, il filtro degli antenati, i filtri delle proprietà e gli ordini di ordinamento. Non è possibile recuperare i risultati utilizzando un cursore senza impostare la stessa query da cui è stato generato in origine.
- Poiché gli operatori
NOT_EQUAL
eIN
sono implementati con più query, le query che li utilizzano non supportano i cursori, né le query composite costruite con il metodoCompositeFilterOperator.or
. - I cursori non funzionano sempre come previsto con una query che utilizza un filtro di disuguaglianza o un ordine di ordinamento per una proprietà con più valori. La logica di deduplica per queste proprietà con più valori non persiste tra i recuperi, pertanto lo stesso risultato potrebbe essere restituito più volte.
- Le nuove release di App Engine potrebbero modificare i dettagli di implementazione interna, invalidando i cursori che dipendono da questi. Se un'applicazione tenta di utilizzare un cursore non più valido, Datastore genera un
IllegalArgumentException
(API di basso livello),JDOFatalUserException
(JDO) oPersistenceException
(JPA).
Cursori e aggiornamenti dei dati
La posizione del cursore è definita come la posizione nell'elenco dei risultati dopo l'ultimo risultato restituito. Un cursore non è una posizione relativa nell'elenco (non è un offset); è un indicatore a cui Datastore può saltare quando avvia una scansione dell'indice per i risultati. Se i risultati di una query cambiano tra un utilizzo e l'altro di un cursore, la query rileva solo le modifiche che si verificano nei risultati dopo il cursore. Se un nuovo risultato viene visualizzato prima della posizione del cursore per la query, non verrà restituito quando vengono recuperati i risultati successivi al cursore. Analogamente, se un'entità non è più un risultato per una query, ma è stata visualizzata prima del cursore, i risultati visualizzati dopo il cursore non cambiano. Se l'ultimo risultato restituito viene rimosso dal set di risultati, il cursore sa ancora come trovare il risultato successivo.
Quando recuperi i risultati delle query, puoi utilizzare sia un cursore di inizio sia un cursore di fine per restituire un gruppo continuo di risultati da Datastore. Quando utilizzi un cursore di inizio e di fine per recuperare i risultati, non è garantito che le dimensioni dei risultati siano le stesse di quando hai generato i cursori. Le entità possono essere aggiunte o eliminate da Datastore tra il momento in cui vengono generati i cursori e il momento in cui vengono utilizzati in una query.
Passaggi successivi
- Scopri come specificare cosa restituisce una query e come controllare ulteriormente i risultati della query.
- Scopri le limitazioni comuni per le query su Datastore.
- Comprendi la coerenza dei dati e come funziona con diversi tipi di query su Datastore.
- Scopri la sintassi e la struttura di base delle query per Datastore.