A RetroSearch Logo

Home - News ( United States | United Kingdom | Italy | Germany ) - Football scores

Search Query:

Showing content from https://cloud.google.com/appengine/docs/legacy/standard/python/datastore/query-cursors below:

Query Cursors | App Engine standard environment for Python 2

Skip to main content Query Cursors

Stay organized with collections Save and categorize content based on your preferences.

Query cursors allow an application to retrieve a query's results in convenient batches, and are recommended over using integer offsets for pagination. See Queries for more information on structuring queries for your app.

Query cursors

Query cursors allow an application to retrieve a query's results in convenient batches without incurring the overhead of a query offset. After performing a retrieval operation, the application can obtain a cursor, which is an opaque base64-encoded string marking the index position of the last result retrieved. The application can save this string, for example in Datastore, in Memcache, in a Task Queue task payload, or embedded in a web page as an HTTP GET or POST parameter, and can then use the cursor as the starting point for a subsequent retrieval operation to obtain the next batch of results from the point where the previous retrieval ended. A retrieval can also specify an end cursor, to limit the extent of the result set returned.

Offsets versus cursors

Although Datastore supports integer offsets, you should avoid using them. Instead, use cursors. Using an offset only avoids returning the skipped entities to your application, but these entities are still retrieved internally. The skipped entities do affect the latency of the query, and your application is billed for the read operations required to retrieve them. Using cursors instead of offsets lets you avoid all these costs.

Query cursor example

In Python, an application obtains a cursor after retrieving query results by calling the Query object's cursor() method. To retrieve additional results from the point of the cursor, the application prepares a similar query with the same entity kind, filters, and sort orders, and passes the cursor to the query's with_cursor() method before performing the retrieval:

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)
Note: Because of the way the iterator interface retrieves results in batches, getting a cursor may result in an additional call to Datastore to position the cursor where the iterator left off. If using only a start cursor, and if you know how many results you need ahead of time, it's faster to use fetch(). Caution: Be careful when passing a Datastore cursor to a client, such as in a web form. Although the client cannot change the cursor value to access results outside of the original query, it is possible for it to decode the cursor to expose information about result entities, such as the application ID, entity kind, key name or numeric ID, ancestor keys, and properties used in the query's filters and sort orders. If you don't want users to have access to that information, you can encrypt the cursor, or store it and provide the user with an opaque key. Limitations of cursors

Cursors are subject to the following limitations:

Cursors and data updates

The cursor's position is defined as the location in the result list after the last result returned. A cursor is not a relative position in the list (it's not an offset); it's a marker to which Datastore can jump when starting an index scan for results. If the results for a query change between uses of a cursor, the query notices only changes that occur in results after the cursor. If a new result appears before the cursor's position for the query, it will not be returned when the results after the cursor are fetched. Similarly, if an entity is no longer a result for a query but had appeared before the cursor, the results that appear after the cursor do not change. If the last result returned is removed from the result set, the cursor still knows how to locate the next result.

When retrieving query results, you can use both a start cursor and an end cursor to return a continuous group of results from Datastore. When using a start and end cursor to retrieve the results, you are not guaranteed that the size of the results will be the same as when you generated the cursors. Entities may be added or deleted from Datastore between the time the cursors are generated and when they are used in a query.

What's next?

Except as otherwise noted, the content of this page is licensed under the Creative Commons Attribution 4.0 License, and code samples are licensed under the Apache 2.0 License. For details, see the Google Developers Site Policies. Java is a registered trademark of Oracle and/or its affiliates.

Last updated 2025-08-07 UTC.

[[["Easy to understand","easyToUnderstand","thumb-up"],["Solved my problem","solvedMyProblem","thumb-up"],["Other","otherUp","thumb-up"]],[["Hard to understand","hardToUnderstand","thumb-down"],["Incorrect information or sample code","incorrectInformationOrSampleCode","thumb-down"],["Missing the information/samples I need","missingTheInformationSamplesINeed","thumb-down"],["Other","otherDown","thumb-down"]],["Last updated 2025-08-07 UTC."],[[["Query cursors allow applications to retrieve query results in batches, marking the position of the last retrieved result as an opaque, base64-encoded string."],["Using cursors instead of integer offsets is recommended because offsets still retrieve skipped entities internally, affecting latency and incurring read operation costs."],["Cursors can be saved and used later to continue a query from where it left off, allowing applications to get the next batch of results."],["Cursors have limitations, such as only being usable by the same application for the same query and not supporting `!=` and `IN` operators."],["The position of a cursor is defined as the location after the last returned result, and while it is not affected by results that come before the cursor, new additions or removals after the cursor can impact results."]]],[]]


RetroSearch is an open source project built by @garambo | Open a GitHub Issue

Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo

HTML: 3.2 | Encoding: UTF-8 | Version: 0.7.4