Alfred Fuller
September 2011
This is one of a series of in-depth articles discussing App Engine's datastore. To see the other articles in the series, see Related links .
The App Engine Datastore supports a fast and efficient means of querying large data sets while providing a relatively flexible set of SQL-like features. We accomplish this by shifting most of the querying cost from query time to write time through prebuilt indexes. Doing so requires knowing the form of all queries that can be possibly run in your application.
However, there are situations where it's impossible to know the exact form of a query ahead of time, like when the filters of the query are constructed dynamically based on user input. In these cases, all possible combinations of filters must be supported by the indexes defined by the application. Traditionally, this has required a combinatorial explosion in the number of indexes defined. Recent enhancements to the App Engine Datastore query planner have eliminated the requirement for such a proliferation in an application's indexes. This article describes how to take full advantage of these enhancements.
For brevity, we are using a shorthand notation for index definitions. The following definition denotes an index of kind
model
, with property
prop1
ascending and
prop2
descending:
Index(model, prop1, -prop2)
This is equivalent to the following configuration in
index.yaml
:
indexes: - kind: model ancestor: no properties: - name: prop1 - name: prop2 direction: desc
or this configuration in
datastore-indexes.xml
:
<datastore-indexes> <datastore-index kind="model" ancestor="false"> <property name="prop1" direction="asc" /> <property name="prop2" direction="desc" /> </datastore-index> </datastore-indexes>
For more information, see Index Configuration ( Python | Java ).
Consider the following definition for a "Photo" entity:
Photo | ||
---|---|---|
Property | Value type | Meaning |
owner_id
|
String | User id |
tag
|
List of strings | Tokenized keywords |
size
|
Integer |
Enum:
|
license
|
Integer |
Enum:
|
aspect
|
Integer |
Enum:
|
coloration
|
Integer |
Enum:
|
date_added
|
Integer | Date/time |
rating
|
Float | Aggregate user rating |
comment_count
|
Integer | Number of comments |
download_count
|
Integer | Number of downloads |
If you know that you will be running queries of the form
SELECT * FROM Photo WHERE license=<reuse> ORDER BY date_added DESC
The following index must be added to your application at deployment time:
Index(Photo, license, -date)
If this index does not exist, the datastore returns a NeedIndexError in Python, or a DatastoreNeedIndexException in Java, every time this query is run.
For more information, see the Introduction to Indexes ( Python | Java ).
Advanced Search
As an example, let's create an "Advanced Search" feature for photos. A fully interactive version of this form is available at http://advanced-search-demo.appspot.com/ . Users can specify the following options: