English

Google App Engine

The Query Class

The Query class is a datastore query interface that uses objects and methods to prepare queries.

Query is provided by the google.appengine.ext.db module.

Introduction

An application creates a Query object by calling either the Model class's all() class method or the Query constructor.

class Song(db.Model):
    title = db.StringProperty()
    composer = db.StringProperty()
    date = db.DateTimeProperty()

query = Song.all()

query = db.Query(Song)

ancestor = Song.get_by_key_name('my_song')
query = db.Query(ancestor)

Without modification, the object represents a query for all entities with a specific kind or ancestor (for "kindless" queries). Method calls customize the query with property conditions (filter()), ancestor conditions (ancestor()), and ordering (order()). For convenience, these methods return self so that they can combined in a single statement.

query.filter('title =', 'Imagine')
query.order('-date')
query.ancestor(key)

query.filter('title =', 'Imagine').order('-date').ancestor(key)

The application executes the query in one of two ways:

  • by calling the fetch() method. This performs a single call to the datastore to fetch results, up to the specified number of results. The Query object does not cache results, so calling fetch() a second time re-executes the query.

    results = query.fetch(limit=5)
    for song in results:
        print song.title
    
  • by treating the Query object as an iterable. The iterator retrieves results from the datastore in small batches, allowing for the app to stop iterating on results to avoid fetching more than is needed. Iteration stops when all of the results that match the query have been retrieved. As with fetch(), the iterator interface does not cache results, so creating a new iterator from the Query object re-executes the query.

    for song in query:
        print song.title
    
  • See also GqlQuery, a query class that uses a SQL-like query language.

    Note: The index-based data structures and algorithms that power datastore queries do not support some kinds of queries. See Queries and Indexes: Restrictions on Queries for more information.

    Constructor

    The constructor of the Query class is defined as follows:

    class Query(model_class, keys_only=False)

    A datastore query interface that uses objects and methods to prepare queries.

    The Query instance returned by the constructor represents a query for all entities of the kind. The instance methods filter(), order() and ancestor() apply criteria to the query to filter or order the results.

    Arguments:

    model_class
    The class of the Model (or Expando) that represents the datastore entity kind for the query.
    keys_only

    Whether the query should return full entities or just keys. Queries that return keys are faster and cost less CPU than queries that return full entities.

    Instance Methods

    Instances of the Query class have the following methods:

    filter(property_operator, value)

    Adds a property condition filter to the query. The query returns only entities with properties that meet all of the conditions.

    Arguments:

    property_operator
    A string containing the property name, and an optional comparison operator. The name and the operator must be separated by a space, as in: age >. The following comparison operators are supported: < <= = >= > != IN. If the operator is omitted from the string (the argument is just the property name), the filter uses the = operator.
    value
    The value to use in the comparison on the right-hand side of the expression. Its type should be the value data type for the property being compared. See Types and Property Classes.
    query.filter('height >', 42).filter('city = ', 'Seattle')
    
    query.filter('user = ', users.get_current_user())
    
    order(property)

    Adds an ordering for the results. Results are ordered starting with the first order added.

    Arguments:

    property
    A string, the name of the property to order. To specify that the order ought to be in descending order, precede the name with a hyphen (-). Without a hyphen, the order is ascending.
    # Order by last name, alphabetical:
    query.order('last_name')
    
    # Order tallest to shortest:
    query.order('-height')
    
    ancestor(ancestor)

    Adds an ancestor condition filter to the query. The query returns only entities with the given entity as an ancestor (anywhere in its path).

    Arguments:

    ancestor
    A Model instance or Key instance representing the ancestor.
    get(config=None)

    Executes the query, then returns the first result, or None if the query returned no results.

    get() fetches a "limit" of one result, at most.

    Arguments:

    config
    A configuration object for the API call.
    fetch(limit, offset=0, config=None)

    Executes the query, then returns the results.

    The limit and offset arguments control how many results are fetched from the datastore, and how many are returned by the fetch() method:

    • The datastore fetches offset + limit results.
    • The first offset results are skipped by the datastore and not sent to the application.
    • The fetch() method then returns the rest (limit results).

    Note: The query has performance characteristics that correspond linearly with the offset amount plus the limit amount.

    Arguments:

    limit

    The number of results to return. Fewer than limit results may be returned if not enough results are available that meet the criteria.

    limit is a required argument. To get every result from a query when the number of results is unknown, use the Query object as an iterable instead of using the fetch() method.

    offset
    The number of results to skip.
    config
    A configuration object for the API call.

    The return value is a list of model instances or keys, possibly an empty list.

    run(config=None)

    Runs the query, and returns an iterable of the results. This allows you to use an configuration object for the call, and access results with an iterable interface. If you are not using an configuration object, you can just use the Query (or GqlQuery) object as the iterable to execute the query.

    Arguments:

    config
    A configuration object for the API call.
    count(limit, config=None)

    Returns the number of results this query fetches.

    count() is somewhat faster than retrieving all of the data by a constant factor, but the running time still grows with the size of the result set. It's best to only use count() in cases where the count is expected to be small, or specify a limit.

    count() has no maximum limit. If you don't specify a limit, the datastore continues counting until it finishes counting or times out.

    Arguments:

    limit

    The maximum number of results to count.

    config
    A configuration object for the API call.
    index_list()

    Returns a list of indexes used by the executed query. If you invoke this on a query that has not yet run, you'll get an AssertionError.

    The indexes returned can be composite indexes, primary indexes, kind indexes, and single-property indexes.

    This feature is not fully supported on the development server. When used with the development server, the result is either the empty list or a list containing exactly one composite index.

    The following snippet shows one way to process the index list returned by this method call:

    # other imports ...
    from google.appengine.ext import webapp
    from google.appengine.ext.webapp.util import run_wsgi_app
    from google.appengine.api import users
    from google.appengine.ext import db
    from google.appengine.api import datastore
    
    class Greeting(db.Model):
      author = db.UserProperty()
      content = db.StringProperty(multiline=True)
      date = db.DateTimeProperty(auto_now_add=True)
    
    
    class MainPage(webapp.RequestHandler):
      def get(self):
        user = users.get_current_user()
        q = db.Query(Greeting)
        q.filter("author =", user.nickname())
        q.order("-date")
        q.fetch(100)
        index_list = q.index_list()
        for indx in index_list:
          self.response.out.write("Kind: %s" % indx.kind())
          self.response.out.write("<br />")
          self.response.out.write("Has ancestor? %s" % indx.has_ancestor())
          self.response.out.write("<br />")
          for name, direction in indx.properties():
            self.response.out.write("Property name: "+name)
            self.response.out.write("<br />")
            if direction == datastore.Query.DESCENDING:
              self.response.out.write("Sort direction: DESCENDING")
            else:
              self.response.out.write("Sort direction: ASCENDING")
            self.response.out.write("<br />")
    

    The snippet queries for an object called Greetings, filtering by the author property. After the fetch, the returned list of indexes is processed and various information about the index is extracted, such as the object Kind, filters, sort orders used, and sort direction, as shown below:

    Kind: Greeting
    Has ancestor? False
    Property name: author
    Sort direction: ASCENDING
    Property name: date
    Sort direction: DESCENDING
    
    cursor()

    Returns an encoded cursor that represents the location in the result set after the last result fetched. A future invocation of the same query can provide this cursor using with_cursor() to start fetching results from this location.

    You must fetch results (using either fetch() or the iterator interface) before you can get a cursor, otherwise you'll get an AssertionError.

    The cursor is a base64-encoded string. It is safe to use in HTTP GET and POST parameters, and can also be stored in the datastore or memcache.

    Note: Not all queries are compatible with cursors. See Query Cursors for more information.

    with_cursor(start_cursor, end_cursor=None)

    Tells the datastore to start returning results from the location associated with the given encoded start cursor. If present, stops returning results at the end cursor. An app gets the cursor for a location in a list of results by calling cursor() after fetching results.

    The query must be identical to the query that generated the cursor, including the kind, property filters, ancestor filters, and sort orders.

    The app must call this method before fetching any results (i.e. before executing the query).

    Arguments:

    start_cursor

    The base64-encoded cursor returned by the cursor() method in a previous invocation of the query. Indicates where to start the query.

    end_cursor

    The base64-encoded cursor returned by the cursor() method in a previous invocation of the query. Indicates where to end the query.