Optimizing queries in Haystack results

My [Adobe software updates][asu] app (which uses [Haystack][haystack] + [Django][django] to provide a search feature) has a very inefficient search results template, where for each search result the template links back to the update’s related product page.

The meat of the search results template looks something like this:

{% for result in page.object_list %}

{% endfor %}

The reverse URL lookup triggers a separate SQL query to find the related product object’s slug field for each object in the results list, and that slows down the page response significantly.

For a regular queryset you would [tell Django to fetch the related objects][select-related] in one go when populating the template context in order to avoid the extra queries, but in this case `page.object_list` is generated by Haystack. So how to tell Haystack to use `select_related()` for the queryset?

It is easy. When you register a model to be indexed with Haystack for searching, you have to define a `SearchIndex` model, and you can also override the [`read_queryset()` method that is used by Haystack to get a Django queryset][rq]:

# myapp.search_indexes.py
from haystack import indexes, site
from myapp.models import MyModel

class MyModelIndex(indexes.SearchIndex):
# Indexed fields declared here

def get_model(self):
return MyModel

def read_queryset(self):
return self.model.objects.select_related()

site.register(MyModel, MyModelIndex)

And that solved it for me. Shaves three quarters off the execution time.

PS This all pertains to Django 1.4 and Haystack 1.2.7.

PPS Also pertains to a version of my Adobe software updates page that I haven’t deployed quite yet.

[haystack]: http://haystacksearch.org/
[django]: https://www.djangoproject.com/
[asu]: http://reliablybroken.com/wavesinspace/adobe/
[select-related]: https://docs.djangoproject.com/en/1.4/ref/models/querysets/#select-related
[rq]: http://django-haystack.readthedocs.org/en/v1.2.7/searchindex_api.html#read-queryset

Leave a Reply

Your email address will not be published. Required fields are marked *