Full text indexing and search, implemented in pure python.

Defines a SearchableModel subclass of db.Model that supports full text indexing and search, based on the datastore’s existing indexes.

Don’t expect too much. First, there’s no ranking, which is a killer drawback. There’s also no exact phrase match, substring match, boolean operators, stemming, or other common full text search features. Finally, support for stop words (common words that are not indexed) is currently limited to English.

To be indexed, entities must be created and saved as SearchableModel instances, e.g.:

class Article(search.SearchableModel):

text = db.TextProperty() …

article = Article(text=…)

To search the full text index, use the SearchableModel.all() method to get an instance of SearchableModel.Query, which subclasses db.Query. Use its search() method to provide a search query, in addition to any other filters or sort orders, e.g.:

query = article.all().search(‘a search query’).filter(…).order(…) for result in query:

The full text index is stored in a property named __searchable_text_index.

Specifying multiple indexes and properties to index

By default, one index is created with all string properties. You can define multiple indexes and specify which properties should be indexed for each by overriding SearchableProperties() method of model.SearchableModel, for example:

class Article(search.SearchableModel):

@classmethod def SearchableProperties(cls):

return [[‘book’, ‘author’], [‘book’]]

In this example, two indexes will be maintained - one that includes ‘book’ and ‘author’ properties, and another one for ‘book’ property only. They will be stored in properties named __searchable_text_index_book_author and __searchable_text_index_book respectively. Note that the index that includes all properties will not be created unless added explicitly like this:

@classmethod def SearchableProperties(cls):

return [[‘book’, ‘author’], [‘book’], search.ALL_PROPERTIES]

The default return value of SearchableProperties() is [search.ALL_PROPERTIES] (one index, all properties).

To search using a custom-defined index, pass its definition in ‘properties’ parameter of ‘search’:

Article.all().search(‘Lem’, properties=[‘book’, ‘author’])

Note that the order of properties in the list matters.

Adding indexes to index.yaml

In general, if you just want to provide full text search, you don’t need to add any extra indexes to your index.yaml. However, if you want to use search() in a query in addition to an ancestor, filter, or sort order, you’ll need to create an index in index.yaml with the __searchable_text_index property. For .. rubric:: example

  • kind: Article properties: - name: __searchable_text_index - name: date

    direction: desc

Similarly, if you created a custom index (see above), use the name of the property it’s stored in, e.g. __searchable_text_index_book_author.

Note that using SearchableModel will noticeable increase the latency of save() operations, since it writes an index row for each indexable word. This also means that the latency of save() will increase roughly with the size of the properties in a given entity. Caveat hacker!

class, word_delimiter_regex=None, *args, **kwargs)source

Bases: google.appengine.api.datastore.Entity

A subclass of datastore.Entity that supports full text indexing.

Automatically indexes all string and Text properties, using the datastore’s built-in per-property indices. To search, use the SearchableQuery class and its Search() method.

classmethod IndexPropertyName(properties)source

Given index definition, returns the name of the property to put it in.

class, key_name=None, _app=None, _from_entity=False, **kwds)source

Bases: google.appengine.ext.db.Model

A subclass of db.Model that supports full text search and indexing.

Automatically indexes all string-based properties. To search, use the all() method to get a SearchableModel.Query, then use its search() method.

Override SearchableProperties() to define properties to index and/or multiple indexes (see the file’s comment).

class Query(model_class=None, keys_only=False, cursor=None, namespace=None, _app=None, distinct=False, projection=None)source

Bases: google.appengine.ext.db.Query

A subclass of db.Query that supports full text search.

search(search_query, properties=[])source

Adds a full text search to this query.


a string containing the full text search query. (search_query,) –



classmethod SearchableProperties()source
classmethod all()source

Returns a SearchableModel.Query for this kind.

classmethod from_entity(entity)source

Wraps db.Model.from_entity() and injects SearchableEntity.

class, orderings)source

Bases: google.appengine.api.datastore.MultiQuery

A multiquery that supports Search() by searching subqueries.

Search(*args, **kwargs)source

Add a search query, by trying to add it to all subqueries.

  • args – Passed to Search on each subquery.

  • kwargs – Passed to Search on each subquery.


self for consistency with SearchableQuery.

class, filters={}, _app=None, keys_only=False, compile=True, cursor=None, namespace=None, end_cursor=None, projection=None, distinct=None, _namespace=None)source

Bases: google.appengine.api.datastore.Query

A subclass of datastore.Query that supports full text search.

Only searches over entities that were created and stored using the SearchableEntity or SearchableModel classes.

GetFilterPredicate(*args, **kwds)source

Adds filters for the search query, then delegates to the superclass.

Mimics Query.GetFilterPredicate()’s signature. Raises BadFilterError if a filter on the index property already exists.



Search(search_query, word_delimiter_regex=None, properties=[])source

Add a search query. This may be combined with filters.

Note that keywords in the search query will be silently dropped if they are stop words or too short, ie if they wouldn’t be indexed.


search_query – string


# this query SearchableQuery