I'm playing around with a relatively straightforward implementation of Whoosh 2.6 and django-haystack 2.3.1 for a search of "contact" objects. However, an example search for "mary" only returns a small subset of my many "Mary" contacts. Here are the relevant files:
search_indexes.py
from django.db.models import Q
from haystack import indexes
from apps.contact.models import Contact
class ContactIndex(indexes.SearchIndex, indexes.Indexable):
text = indexes.CharField(document=True, use_template=True)
full_name = indexes.CharField(model_attr='full_name', null=True)
email = indexes.CharField(model_attr='email', null=True)
phone = indexes.CharField(model_attr='phone', null=True)
content_auto = indexes.NgramField(use_template=True)
# several more indexed=False fields to avoid db hits later
def get_model(self):
return Contact
def index_queryset(self, **kwargs):
# one of full_name, email, phone has to be non-null
return self.get_model().objects.filter(
Q(full_name__isnull=False) | Q(email__isnull=False) | Q(phone__isnull=False))
def get_updated_field(self):
return 'date_modified'
contact_text.txt and contact_content_auto.txt (both the same)
{% if object.full_name %}{{ object.full_name }}{% else %}{% endif %}
{% if object.email %}{{ object.email }}{% else %}{% endif %}
{% if object.phone %}{{ object.phone }}{% else %}{% endif %}
views.py
def search(request):
sqs = SearchQuerySet()
form = SearchForm(request.POST, searchqueryset=sqs, load_all=False)
if form.is_valid():
return form.search()
Relevant notes:
- some code has been omitted for simplicity
- the templates have if statements in order to get rid of the word "None" in the search index
- currently, all of my Contact objects have a valid full_name
- there is no pattern to which "mary" results are returned and which aren't:
select count(*) from contact_contact where lower(full_name) like '%mary%';
returns 97 rows, while the search returns only 5. Similarly, for 483 "john" contacts, the search returns 19. - using Python 2.7, Django 1.5 and Postgres 8.4