From de76bad3f05eb7937aefac3f5b0d3ef1d126b526 Mon Sep 17 00:00:00 2001 From: Claude Paroz Date: Fri, 14 Oct 2016 18:04:20 +0200 Subject: [PATCH] Fixed #161 -- Supported range search filter `range` was added in django-haystack commit 3994bfa199. --- tests/xapian_tests/tests/test_query.py | 9 +++++++++ xapian_backend.py | 17 +++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/tests/xapian_tests/tests/test_query.py b/tests/xapian_tests/tests/test_query.py index 1959bcf..f64acdc 100644 --- a/tests/xapian_tests/tests/test_query.py +++ b/tests/xapian_tests/tests/test_query.py @@ -307,6 +307,15 @@ class SearchQueryTestCase(HaystackBackendTestCase, TestCase): self.sq.add_filter(SQ(name__lte='m')) self.assertExpectedQuery(self.sq.build_query(), 'VALUE_RANGE 3 a m') + def test_range(self): + self.sq.add_filter(SQ(django_id__range=[2, 4])) + self.assertExpectedQuery(self.sq.build_query(), 'VALUE_RANGE 1 000000000002 000000000004') + self.sq.add_filter(~SQ(django_id__range=[0, 2])) + self.assertExpectedQuery(self.sq.build_query(), + '(VALUE_RANGE 1 000000000002 000000000004 AND ' + '( AND_NOT VALUE_RANGE 1 000000000000 000000000002))') + self.assertEqual([result.pk for result in self.sq.get_results()], [3]) + def test_multiple_filter_types(self): self.sq.add_filter(SQ(content='why')) self.sq.add_filter(SQ(pub_date__lte=datetime.datetime(2009, 2, 10, 1, 59, 0))) diff --git a/xapian_backend.py b/xapian_backend.py index 7b563b6..b017505 100755 --- a/xapian_backend.py +++ b/xapian_backend.py @@ -1373,6 +1373,8 @@ class XapianSearchQuery(BaseSearchQuery): query_list.append(self._filter_lt(term, field_name, field_type, is_not)) elif filter_type == 'lte': query_list.append(self._filter_lte(term, field_name, field_type, is_not)) + elif filter_type == 'range': + query_list.append(self._filter_range(term, field_name, field_type, is_not)) return query_list def _all_query(self): @@ -1559,6 +1561,21 @@ class XapianSearchQuery(BaseSearchQuery): ) return xapian.Query(xapian.Query.OP_VALUE_RANGE, pos, begin, end) + def _filter_range(self, term, field_name, field_type, is_not): + """ + Private method that returns a xapian.Query that searches for any term + that is between the values from the `term` list. + """ + vrp = XHValueRangeProcessor(self.backend) + pos, begin, end = vrp('%s:%s' % (field_name, _term_to_xapian_value(term[0], field_type)), + '%s' % _term_to_xapian_value(term[1], field_type)) + if is_not: + return xapian.Query(xapian.Query.OP_AND_NOT, + self._all_query(), + xapian.Query(xapian.Query.OP_VALUE_RANGE, pos, begin, end) + ) + return xapian.Query(xapian.Query.OP_VALUE_RANGE, pos, begin, end) + def _term_to_xapian_value(term, field_type): """