Cursori di query

I cursori di query consentono a un'applicazione di recuperare i risultati di una query in pratici batch. Sono consigliati invece di utilizzare offset interi per l'impaginazione. Consulta la sezione Query per ulteriori informazioni su come strutturare le query per la tua app.

Cursori di query

I cursori di query consentono a un'applicazione di recuperare i risultati di una query in pratici batch senza dover sostenere l'overhead di un offset della 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, in un payload di attività della coda di attività o incorporata in una pagina web come parametro HTTP GET o POST, quindi può 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 finale, per limitare l'estensione del set di risultati restituito.

Offset e cursori

Sebbene Datastore supporti gli offset interi, dovresti evitare di utilizzarli. Utilizza invece i cursori. L'utilizzo di un offset evita solo di restituire le entità ignorate all'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 dei cursori invece delle compensazioni consente di evitare tutti questi costi.

Esempio di cursore di query

In Python, un'applicazione ottiene un cursore dopo aver recuperato i risultati della query chiamando il metodo cursor() dell'oggetto Query. Per recuperare risultati aggiuntivi dal punto del cursore, l'applicazione prepara una query simile con lo stesso tipo di entità, i filtri e gli ordini di ordinamento e passa il cursore al metodo with_cursor() della query prima di eseguire il recupero:

from google.appengine.api import memcache
from google.appengine.ext import db

# class Person(db.Model): ...
    
# Start a query for all Person entities
people = Person.all()
    
# If the application stored a cursor during a previous request, use it
person_cursor = memcache.get('person_cursor')
if person_cursor:
  people.with_cursor(start_cursor=person_cursor)
    
# Iterate over the results
for person in people:
  # Do something
    
# Get updated cursor and store it for next time
person_cursor = people.cursor()
memcache.set('person_cursor', person_cursor)

Limiti 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à, filtro dei predecessori, filtri di proprietà e ordinamento. Non è possibile recuperare i risultati utilizzando un cursore senza impostare la stessa query da cui sono stati originariamente generati.
  • Poiché gli operatori != e IN vengono implementati con più query, le query che li utilizzano non supportano i cursori.
  • I cursori non funzionano sempre come previsto con una query che utilizza un filtro di disuguaglianza o un ordinamento su una proprietà con più valori. La logica di deduplicazione per queste proprietà a più valori non persiste tra i recuperi, e può causare la restituzione dello stesso risultato più di una volta.
  • Le nuove release di App Engine potrebbero modificare i dettagli di implementazione interni, invalidando i cursori che dipendono da questi. Se un'applicazione tenta di utilizzare un cursore che non è più valido, Datastore genera un'eccezione BadRequestError.

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ò passare quando viene avviata una scansione dell'indice dei risultati. Se i risultati di una query cambiano tra gli utilizzi 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 i risultati vengono recuperati dopo il recupero del cursore. Analogamente, se un'entità non è più il risultato di 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 individuare il risultato successivo.

Durante il recupero dei risultati della query, puoi utilizzare sia un cursore di inizio che un cursore finale per restituire un gruppo continuo di risultati da Datastore. Quando utilizzi un cursore di inizio e fine per recuperare i risultati, non è garantito che le dimensioni dei risultati corrispondano a quelle della generazione dei 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.

Che cosa succede dopo?