Implement search with Django-haystack and Elasticsearch Part-I

Haystack works as a search plugin for Django. You can use different backends Elastic-search, Whose, Sorl, Xapian to search objects. All backends work with the same code. In this post, I am using elastic search as backend.

Installation:

pip install django-haystack

Configuration:

add haystack to installed apps

INSTALLED_APPS=[
               'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.sites',
#add haystack here
'haystack',
'books'
]

Settings:

Add back-end settings for the haystack.

HAYSTACK_CONNECTIONS = {
'default': {
'ENGINE': 'haystack.backends.elasticsearch_backend.ElasticsearchSearchEngine',
'URL': 'http://127.0.0.1:9200/',
'INDEX_NAME': 'haystack_books',
},
}

Above settings for elastic search.

Add signal processor for the haystack. This signal will update objects in an index.

HAYSTACK_SIGNAL_PROCESSOR = 'haystack.signals.RealtimeSignalProcessor'

For This tutorial, I am using below as a model.

books/models.py:

class Book(models.Model):
title = models.CharField(max_length=100, unique=True)
slug = models.SlugField(unique=True)
created_on = models.DateTimeField(auto_now_add=True)
description = models.TextField()
authors = models.ManyToManyField(settings.AUTH_USER_MODEL)

def __unicode__(self):
return self.title

SearchIndex:

The purpose of indexing objects is to optimize speed and performance in finding relevant documents for a given search query.
 With search index haystack determines what data should be placed in the index. In haystack, you write a unique index for each model.

create a new file in books/search_indexes.py below code goes

from haystack import indexes
from books.models import Book
    class BookIndex(indexes.SearchIndex, indexes.Indexable):
text = indexes.CharField(document=True, use_template=True, template_name="search/book_text.txt")
title = indexes.CharField(model_attr='title')
authors = indexes.CharField()
        def get_model(self):
return Book
        def prepare_authors(self, obj):
return [ author.name for a in obj.authors.all()]
        def index_queryset(self, using=None):
return self.get_model().objects.all()

search index will be created by subclassing both haystack.Indexes.SearchIndex and haystack.Indexes.Indexable. Specify index field types by indexes field types(similar to models).

in above index class get_model method used to define a model which you want to create indexes. prepare_fieldname method used to define data for indexing.

Haystack will use a template to index data. these index syntaxes are similar to Django template tags.

templates/search/book_text.txt

{{ object.title }}
{% for a in authors%}
{{ a }}
{% endfor %}

Setup:

urls.py

urlpatterns = patterns(
# other urls
url(r'^search/', include('haystack.urls')),
)

build index:

Python manage.py rebuild_index

search query form.

<form action="/search" method="get">
<input name="q" type="text" />
<input type="submit" />
</form>

input field q is mandatory for searching.

Display search results:

belove code goes in templates/search/search.html

{% for result in page.object_list %}
{{ result.object.title }}
{{ result.object.description }}
{{ result.object.created_on }}
{% empty %}
No results found.
{% endfor %}

Got error or want to give suggestions please comment below. Happy Coding.

The article was originally published at MicroPyramid blog.