From 11ba78f42d78dc5593e345b104026d53a6b64cf8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20C=2E=20Leit=C3=A3o?= Date: Fri, 13 Jun 2014 19:51:07 +0200 Subject: [PATCH] Fixed #129 -- auto_query now works as expected. Modified tests since "text" is the main document, which doesn't make sense to use "startswith". --- tests/xapian_tests/tests/test_interface.py | 4 ++-- xapian_backend.py | 25 ++++++++++++++++------ 2 files changed, 20 insertions(+), 9 deletions(-) diff --git a/tests/xapian_tests/tests/test_interface.py b/tests/xapian_tests/tests/test_interface.py index 343765b..c485e68 100644 --- a/tests/xapian_tests/tests/test_interface.py +++ b/tests/xapian_tests/tests/test_interface.py @@ -135,8 +135,8 @@ class InterfaceTestCase(TestCase): def test_field_startswith(self): self.assertEqual(len(self.queryset.filter(name__startswith='magaz')), 4) - self.assertEqual(set(pks(self.queryset.filter(text__startswith='This is'))), - set(pks(Document.objects.filter(text__startswith='This is')))) + self.assertEqual(set(pks(self.queryset.filter(summary__startswith='This is a huge'))), + set(pks(Document.objects.filter(summary__startswith='This is a huge')))) def test_auto_query(self): # todo: improve to query text only. diff --git a/xapian_backend.py b/xapian_backend.py index 7a8e4c1..42b0895 100755 --- a/xapian_backend.py +++ b/xapian_backend.py @@ -14,7 +14,7 @@ from django.utils.encoding import force_text from haystack import connections from haystack.backends import BaseEngine, BaseSearchBackend, BaseSearchQuery, SearchNode, log_query -from haystack.constants import ID, DJANGO_ID, DJANGO_CT +from haystack.constants import ID, DJANGO_ID, DJANGO_CT, DEFAULT_OPERATOR from haystack.exceptions import HaystackError, MissingDependency from haystack.inputs import AutoQuery from haystack.models import SearchResult @@ -49,6 +49,13 @@ DEFAULT_XAPIAN_FLAGS = ( xapian.QueryParser.FLAG_PURE_NOT ) +# Mapping from `HAYSTACK_DEFAULT_OPERATOR` to Xapian operators +XAPIAN_OPTS = {'AND': xapian.Query.OP_AND, + 'OR': xapian.Query.OP_OR, + 'PHRASE': xapian.Query.OP_PHRASE, + 'NEAR': xapian.Query.OP_NEAR + } + # number of documents checked by default when building facets # this must be improved to be relative to the total number of docs. DEFAULT_CHECK_AT_LEAST = 1000 @@ -750,6 +757,7 @@ class XapianSearchBackend(BaseSearchBackend): qp.set_database(self._database()) qp.set_stemmer(xapian.Stem(self.language)) qp.set_stemming_strategy(xapian.QueryParser.STEM_SOME) + qp.set_default_op(XAPIAN_OPTS[DEFAULT_OPERATOR]) qp.add_boolean_prefix('django_ct', TERM_PREFIXES['django_ct']) for field_dict in self.schema: @@ -1340,13 +1348,16 @@ class XapianSearchQuery(BaseSearchQuery): Assumes term is not a list. """ - # TODO: if field_type is of type integer, we need to marsh the value. - if field_name: - query_string = '%s:%s*' % (field_name, term) + if field_type == 'text': + if len(term.split()) == 1: + term = '^ %s*' % term + query = self.backend.parse_query(term) + else: + term = '^ %s' % term + query = self._phrase_query(term.split(), field_name, field_type) else: - query_string = '%s*' % term - - query = self.backend.parse_query(query_string) + term = '^%s*' % term + query = self.backend.parse_query(term) if is_not: return xapian.Query(xapian.Query.OP_AND_NOT, self._all_query(), query)