From eb9c4f9777a2b26024e6bdbd2b8a94e2c8f1b135 Mon Sep 17 00:00:00 2001 From: David Sauve Date: Tue, 10 Nov 2009 21:31:25 -0500 Subject: [PATCH] Four tests passing now. Recursively parsing the search nodes and negated on NOT as required. --- tests/xapian_tests/tests/xapian_query.py | 8 ++--- xapian_backend.py | 39 ++++++++++++++++-------- 2 files changed, 30 insertions(+), 17 deletions(-) diff --git a/tests/xapian_tests/tests/xapian_query.py b/tests/xapian_tests/tests/xapian_query.py index a3a5cbd..0509f2d 100644 --- a/tests/xapian_tests/tests/xapian_query.py +++ b/tests/xapian_tests/tests/xapian_query.py @@ -61,10 +61,10 @@ class XapianSearchQueryTestCase(TestCase): self.sq.add_filter(SQ(content='world')) self.assertEqual(self.sq.build_query().get_description(), 'Xapian::Query((hello AND world))') - # def test_build_query_multiple_words_not(self): - # self.sq.add_filter(~SQ(content='hello')) - # self.sq.add_filter(~SQ(content='world')) - # self.assertEqual(self.sq.build_query().get_description(), 'Xapian::Query((NOT hello NOT world))') + def test_build_query_multiple_words_not(self): + self.sq.add_filter(~SQ(content='hello')) + self.sq.add_filter(~SQ(content='world')) + self.assertEqual(self.sq.build_query().get_description(), 'Xapian::Query((( AND_NOT hello) AND ( AND_NOT world)))') # def test_build_query_multiple_words_or(self): # self.sq.add_filter('content', 'hello', use_or=True) diff --git a/xapian_backend.py b/xapian_backend.py index 1d16ac5..7379469 100755 --- a/xapian_backend.py +++ b/xapian_backend.py @@ -15,7 +15,7 @@ # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. __author__ = 'David Sauve' -__version__ = (1, 0, 0, 'beta') +__version__ = (2, 0, 0, 'alpha') import time import datetime @@ -30,7 +30,7 @@ from django.conf import settings from django.core.exceptions import ImproperlyConfigured from django.utils.encoding import smart_unicode, force_unicode -from haystack.backends import BaseSearchBackend, BaseSearchQuery, log_query +from haystack.backends import BaseSearchBackend, BaseSearchQuery, SearchNode, log_query from haystack.exceptions import MissingDependency from haystack.fields import DateField, DateTimeField, IntegerField, FloatField, BooleanField, MultiValueField from haystack.models import SearchResult @@ -935,19 +935,32 @@ class SearchQuery(BaseSearchQuery): def build_query(self): if not self.query_filter: - query = xapian.Query('') + return xapian.Query('') else: - query_list = [] - - for child in self.query_filter.children: - expression, value = child - query_list.append(value) - - query = xapian.Query(xapian.Query.OP_AND, query_list) - - return query + return self._query_from_search_node(self.query_filter) - def build_query_fragment(self, field, filter_type, value): + def _query_from_search_node(self, search_node, is_not=False): + query_list = [] + + for child in search_node.children: + if isinstance(child, SearchNode): + query_list.append( + xapian.Query( + xapian.Query.OP_AND, + self._query_from_search_node(child, child.negated) + ) + ) + else: + expression, value = child + if is_not: + # DS_TODO: This can almost definitely be improved. + query_list.append(xapian.Query(xapian.Query.OP_AND_NOT, '', value)) + else: + query_list.append(xapian.Query(value)) + + return xapian.Query(xapian.Query.OP_AND, query_list) + + def build_sub_query(self, value): return xapian.Query(value) #