From d1c59752ce5e07970347d7832d61e80ead62f3c3 Mon Sep 17 00:00:00 2001 From: Claude Paroz Date: Fri, 14 Oct 2016 15:08:54 +0200 Subject: [PATCH] Haystack now defaults to __content instead of __contains Echo to commit django-haystack/django-haystack@42f53cda9 --- tests/xapian_tests/tests/test_interface.py | 12 ++++----- tests/xapian_tests/tests/test_query.py | 29 ++++++++++++++-------- xapian_backend.py | 6 ++--- 3 files changed, 27 insertions(+), 20 deletions(-) diff --git a/tests/xapian_tests/tests/test_interface.py b/tests/xapian_tests/tests/test_interface.py index 6fb2db4..159e044 100644 --- a/tests/xapian_tests/tests/test_interface.py +++ b/tests/xapian_tests/tests/test_interface.py @@ -74,18 +74,18 @@ class InterfaceTestCase(TestCase): self.assertEqual(pks(result)[:4], [1, 4, 7, 10]) def test_field_search(self): - self.assertEqual(pks(self.queryset.filter(name='8')), [4]) + self.assertEqual(pks(self.queryset.filter(name__contains='8')), [4]) self.assertEqual(pks(self.queryset.filter(type_name='book')), pks(Document.objects.filter(type_name='book'))) - self.assertEqual(pks(self.queryset.filter(text='text huge')), + self.assertEqual(pks(self.queryset.filter(text__contains='text huge')), pks(Document.objects.filter(text__contains='text huge'))) def test_field_contains(self): - self.assertEqual(pks(self.queryset.filter(summary='huge')), + self.assertEqual(pks(self.queryset.filter(summary__contains='huge')), pks(Document.objects.filter(summary__contains='huge'))) - result = self.queryset.filter(summary='huge summary') + result = self.queryset.filter(summary__contains='huge summary') self.assertEqual(sorted(pks(result)), pks(Document.objects.all())) @@ -103,7 +103,7 @@ class InterfaceTestCase(TestCase): self.assertEqual(pks(self.queryset.filter(content='huge').filter(summary='medium')), []) self.assertEqual(len(self.queryset.filter(content='huge this')), 12) - self.assertEqual(len(self.queryset.filter(content='huge this').filter(summary='huge')), 4) + self.assertEqual(len(self.queryset.filter(content='huge this').filter(summary__contains='huge')), 4) def test_content_or(self): self.assertEqual(len(self.queryset.filter(content='huge medium')), 8) @@ -113,7 +113,7 @@ class InterfaceTestCase(TestCase): self.assertEqual(pks(self.queryset.filter(name='8').filter(name='4')), []) def test_field_or(self): - self.assertEqual(pks(self.queryset.filter(name='8 4')), [2, 4]) + self.assertEqual(pks(self.queryset.filter(name__contains='8 4')), [2, 4]) def test_field_in(self): self.assertEqual(set(pks(self.queryset.filter(name__in=['magazine 2', 'article 4']))), diff --git a/tests/xapian_tests/tests/test_query.py b/tests/xapian_tests/tests/test_query.py index 83cc180..6cd8c6c 100644 --- a/tests/xapian_tests/tests/test_query.py +++ b/tests/xapian_tests/tests/test_query.py @@ -43,15 +43,15 @@ class XapianSearchQueryTestCase(HaystackBackendTestCase, TestCase): '( AND_NOT (Zhello OR hello))') def test_single_word_field_exact(self): - self.sq.add_filter(SQ(foo='hello')) + self.sq.add_filter(SQ(foo__exact='hello')) self.assertExpectedQuery(self.sq.build_query(), - '(ZXFOOhello OR XFOOhello)') + '(XFOO^ PHRASE 3 XFOOhello PHRASE 3 XFOO$)') def test_single_word_field_exact_not(self): self.sq.add_filter(~SQ(foo='hello')) self.assertExpectedQuery(self.sq.build_query(), '( AND_NOT ' - '(ZXFOOhello OR XFOOhello))') + '(XFOO^ PHRASE 3 XFOOhello PHRASE 3 XFOO$))') def test_boolean(self): self.sq.add_filter(SQ(content=True)) @@ -128,15 +128,15 @@ class XapianSearchQueryTestCase(HaystackBackendTestCase, TestCase): self.sq.add_filter(SQ(foo='hello')) self.sq.add_filter(SQ(title='world')) self.assertExpectedQuery(self.sq.build_query(), - '((ZXFOOhello OR XFOOhello) AND' - ' (ZXTITLEworld OR XTITLEworld))') + '((XFOO^ PHRASE 3 XFOOhello PHRASE 3 XFOO$) AND' + ' (XTITLE^ PHRASE 3 XTITLEworld PHRASE 3 XTITLE$))') def test_multiple_word_field_exact_not(self): self.sq.add_filter(~SQ(foo='hello')) self.sq.add_filter(~SQ(title='world')) self.assertExpectedQuery(self.sq.build_query(), - '(( AND_NOT (ZXFOOhello OR XFOOhello)) AND' - ' ( AND_NOT (ZXTITLEworld OR XTITLEworld)))') + '(( AND_NOT (XFOO^ PHRASE 3 XFOOhello PHRASE 3 XFOO$)) AND' + ' ( AND_NOT (XTITLE^ PHRASE 3 XTITLEworld PHRASE 3 XTITLE$)))') def test_or(self): self.sq.add_filter(SQ(content='hello world')) @@ -267,6 +267,13 @@ class SearchQueryTestCase(HaystackBackendTestCase, TestCase): self.assertEqual(self.sq.get_spelling_suggestion(), 'indexed') self.assertEqual(self.sq.get_spelling_suggestion('indxd'), 'indexed') + def test_contains(self): + self.sq.add_filter(SQ(content='circular')) + self.sq.add_filter(SQ(title__contains='haystack')) + self.assertExpectedQuery(self.sq.build_query(), + '((Zcircular OR circular) AND ' + '(ZXTITLEhaystack OR XTITLEhaystack))') + def test_startswith(self): self.sq.add_filter(SQ(name__startswith='da')) self.assertEqual([result.pk for result in self.sq.get_results()], [1, 2, 3]) @@ -328,7 +335,7 @@ class SearchQueryTestCase(HaystackBackendTestCase, TestCase): len(self.sq.get_results()) self.assertEqual(len(connections['default'].queries), 1) self.assertExpectedQuery(connections['default'].queries[0]['query_string'], - '(ZXNAMEbar OR XNAMEbar)') + '(XNAME^ PHRASE 3 XNAMEbar PHRASE 3 XNAME$)') # And again, for good measure. self.sq = connections['default'].get_query() @@ -337,10 +344,10 @@ class SearchQueryTestCase(HaystackBackendTestCase, TestCase): len(self.sq.get_results()) self.assertEqual(len(connections['default'].queries), 2) self.assertExpectedQuery(connections['default'].queries[0]['query_string'], - '(ZXNAMEbar OR XNAMEbar)') + '(XNAME^ PHRASE 3 XNAMEbar PHRASE 3 XNAME$)') self.assertExpectedQuery(connections['default'].queries[1]['query_string'], - '((ZXNAMEbar OR XNAMEbar) AND' - ' (ZXTEXTmoof OR XTEXTmoof))') + '((XNAME^ PHRASE 3 XNAMEbar PHRASE 3 XNAME$) AND' + ' (XTEXT^ PHRASE 3 XTEXTmoof PHRASE 3 XTEXT$))') # Restore. settings.DEBUG = old_debug diff --git a/xapian_backend.py b/xapian_backend.py index d1a9e15..d694abd 100755 --- a/xapian_backend.py +++ b/xapian_backend.py @@ -1331,9 +1331,9 @@ class XapianSearchQuery(BaseSearchQuery): query_list.append(self._filter_contains(term, field_name, field_type, is_not)) # when filter has no filter_type, haystack uses - # filter_type = 'contains'. Here we remove it + # filter_type = 'content'. Here we remove it # since the above query is already doing this - if filter_type == 'contains': + if filter_type == 'content': filter_type = None else: # get the field_type from the backend @@ -1357,7 +1357,7 @@ class XapianSearchQuery(BaseSearchQuery): # todo: we should check that the filter is valid for this field_type or raise InvalidIndexError if filter_type == 'contains': query_list.append(self._filter_contains(term, field_name, field_type, is_not)) - elif filter_type == 'exact': + elif filter_type in ('content', 'exact'): query_list.append(self._filter_exact(term, field_name, field_type, is_not)) elif filter_type == 'in': query_list.append(self._filter_in(term, field_name, field_type, is_not))