Mapping types and Indexables¶
The MappingType class¶
elasticutils.MappingType
lets you centralize concerns
regarding documents you’re storing in your Elasticsearch index.
Lets you tie business logic to search results¶
When you do searches with MappingTypes, you get back those results as an iterable of MappingTypes by default.
For example, say you had a description field and wanted to have a truncated version of it. You could do it this way:
class MyMappingType(MappingType):
# ... missing code here
def description_truncated(self):
return self.description[:100]
results = S(MyMappingType).query(description__text='stormy night')
print list(results)[0].description_truncated()
Lets you link source data to search results¶
You can relate a MappingType to a database model or other source
allowing you to link documents in the Elasticsearch index back to
their origins in a lazy-loading way. This is done by subclassing
MappingType and implementing the get_object()
method. You can then
access the original data using the object
property.
For example:
class MyMappingType(MappingType):
# ... missing code here
def get_object(self):
return self.get_model().objects.get(pk=self._id)
results = S(MyMappingType).filter(height__gte=72)[:1]
first = list(results)[0]
# This prints "height" which comes from the Elasticsearch
# document
print first.height
# This prints "height" which comes from the database data
# that the Elasticsearch document is based on. This is the
# first time ``.object`` is used, so it does the db hit
# here.
print first.object.height
DefaultMappingType¶
The most basic MappingType is the DefaultMappingType which is returned
if you don’t specify a MappingType and also don’t call
elasticutils.S.values_dict()
or
elasticutils.S.values_list()
. The DefaultMappingType lets
you access search result fields as instance attributes or as keys:
res.description
res['description']
The latter syntax is helpful when there are attributes defined on the class that have the same name as the document field or aren’t valid Python names.
For more information¶
See Types and Mappings for documentation on defining mappings in the index.
See elasticutils.MappingType
for documentation on creating
MappingTypes.
The Indexable class¶
elasticutils.Indexable
is a mixin for
elasticutils.MappingType
that has methods and classmethods
for making indexing easier.
Example¶
Here’s an example of a class that subclasses MappingType and Indexable. It’s based on a model called BlogEntry.
class BlogEntryMappingType(MappingType, Indexable):
@classmethod
def get_index(cls):
return 'blog-index'
@classmethod
def get_mapping_type_name(cls):
return 'blog-entry'
@classmethod
def get_model(cls):
return BlogEntry
@classmethod
def get_es(cls):
return get_es(urls=['http://localhost:9200'])
@classmethod
def get_mapping(cls):
return {
'properties': {
'id': {'type': 'integer'},
'title': {'type': 'string'},
'tags': {'type': 'string'}
}
}
@classmethod
def extract_document(cls, obj_id, obj=None):
if obj == None:
obj = cls.get_model().get(id=obj_id)
doc = {}
doc['id'] = obj.id
doc['title'] = obj.title
doc['tags'] = obj.tags
return doc
@classmethod
def get_indexable(cls):
return cls.get_model().get_objects()
With this, I can write code elsewhere in my project that:
- gets the mapping type name and mapping for documents of type “blog-entry”
- gets all the objects that are indexable
- for each object, extracts the Elasticsearch document data and indexes it
When I create my elasticutils.S
object, I’d create it like
this:
s = S(BlogEntryMappingType)
and now by default any search results I get back are instances of the BlogEntryMappingType class.