Improved how __exact works when used with multiple words.

This commit is contained in:
Jorge C. Leitão 2014-05-22 09:31:37 +02:00
parent 85cf58064f
commit 6c135e92f4
4 changed files with 30 additions and 27 deletions

View file

@ -123,10 +123,10 @@ class XapianSimpleMockIndex(indexes.SearchIndex):
return MockModel
def prepare_text(self, obj):
return 'this_is_a_word'
return 'this_is_a_word inside a big text'
def prepare_author(self, obj):
return 'david'
return 'david holland'
def prepare_url(self, obj):
return 'http://example.com/1/'
@ -150,7 +150,7 @@ class XapianSimpleMockIndex(indexes.SearchIndex):
return '22.34'
def prepare_multi_value(self, obj):
return ['tag', 'tag-test', 'tag-test-test']
return ['tag', 'tag-tag', 'tag-tag-tag']
class HaystackBackendTestCase(object):
@ -237,6 +237,8 @@ class BackendIndexationTestCase(HaystackBackendTestCase, TestCase):
self.assertTrue('ZXTEXTthis_is_a_word' in terms)
self.assertTrue('XTEXTthis_is_a_word' in terms)
self.assertFalse('^this_is_a_word inside a big text$' in terms)
def test_author_field(self):
terms = get_terms(self.backend, '-a')
@ -293,18 +295,12 @@ class BackendIndexationTestCase(HaystackBackendTestCase, TestCase):
"""
terms = get_terms(self.backend, '-a')
self.assertTrue('tag' in terms)
self.assertTrue('tag-test' in terms)
self.assertTrue('tag-test-test' in terms)
self.assertTrue('tag-tag' in terms)
self.assertTrue('tag-tag-tag' in terms)
self.assertTrue('XMULTI_VALUEtag' in terms)
self.assertTrue('XMULTI_VALUEtag-test' in terms)
self.assertTrue('XMULTI_VALUEtag-test-test' in terms)
# these and only these terms
# 3 for the exact term (^{term}$)
self.assertEqual(len([term for term in terms if term.startswith('XMULTI_VALUE')]), 6)
# no stem for exact multivalues.
self.assertEqual(len([term for term in terms if term.startswith('ZXMULTI_VALUE')]), 0)
self.assertTrue('XMULTI_VALUEtag-tag' in terms)
self.assertTrue('XMULTI_VALUEtag-tag-tag' in terms)
def test_non_ascii_chars(self):
terms = get_terms(self.backend, '-a')

View file

@ -10,7 +10,7 @@ from haystack.query import SearchQuerySet
from xapian_tests.models import Document
from xapian_tests.search_indexes import DocumentIndex
from xapian_tests.tests.test_backend import pks
from xapian_tests.tests.test_backend import pks, get_terms
class InterfaceTestCase(TestCase):
@ -58,7 +58,7 @@ class InterfaceTestCase(TestCase):
def tearDown(self):
Document.objects.all().delete()
self.backend.clear()
#self.backend.clear()
super(InterfaceTestCase, self).tearDown()
def test_count(self):
@ -139,6 +139,7 @@ class InterfaceTestCase(TestCase):
set(pks(Document.objects.filter(text__startswith='This is'))))
def test_auto_query(self):
# todo: improve to query text only.
self.assertEqual(set(pks(self.queryset.auto_query("huge OR medium"))),
set(pks(Document.objects.filter(Q(text__contains="huge") |
Q(text__contains="medium")))))

View file

@ -169,27 +169,33 @@ class XapianSearchQueryTestCase(HaystackBackendTestCase, TestCase):
self.sq.add_filter(SQ(content='why'))
self.sq.add_filter(SQ(title__in=["A Famous Paper", "An Infamous Article"]))
self.assertEqual(str(self.sq.build_query()),
'Xapian::Query(((Zwhi OR why) AND '
'((XTITLEa PHRASE 3 XTITLEfamous PHRASE 3 XTITLEpaper) OR '
'(XTITLEan PHRASE 3 XTITLEinfamous PHRASE 3 XTITLEarticle))))')
'Xapian::Query(('
'(Zwhi OR why) AND ((XTITLE^ PHRASE 5 XTITLEa PHRASE 5 '
'XTITLEfamous PHRASE 5 XTITLEpaper PHRASE 5 XTITLE$) OR '
'(XTITLE^ PHRASE 5 XTITLEan PHRASE 5 XTITLEinfamous PHRASE 5 '
'XTITLEarticle PHRASE 5 XTITLE$))))')
def test_build_query_in_filter_multiple_words_with_punctuation(self):
self.sq.add_filter(SQ(title__in=["A Famous Paper", "An Infamous Article", "My Store Inc."]))
self.assertEqual(str(self.sq.build_query()),
'Xapian::Query(('
'(XTITLEa PHRASE 3 XTITLEfamous PHRASE 3 XTITLEpaper) OR '
'(XTITLEan PHRASE 3 XTITLEinfamous PHRASE 3 XTITLEarticle) OR '
'(XTITLEmy PHRASE 3 XTITLEstore PHRASE 3 XTITLEinc.)))')
'(XTITLE^ PHRASE 5 XTITLEa PHRASE 5 XTITLEfamous PHRASE 5'
' XTITLEpaper PHRASE 5 XTITLE$) OR '
'(XTITLE^ PHRASE 5 XTITLEan PHRASE 5 XTITLEinfamous PHRASE 5'
' XTITLEarticle PHRASE 5 XTITLE$) OR '
'(XTITLE^ PHRASE 5 XTITLEmy PHRASE 5 XTITLEstore PHRASE 5'
' XTITLEinc. PHRASE 5 XTITLE$)))')
def test_build_query_not_in_filter_multiple_words(self):
self.sq.add_filter(SQ(content='why'))
self.sq.add_filter(~SQ(title__in=["A Famous Paper", "An Infamous Article"]))
self.assertEqual(str(self.sq.build_query()),
'Xapian::Query(((Zwhi OR why) AND '
'(<alldocuments> AND_NOT ((XTITLEa PHRASE 3 '
'XTITLEfamous PHRASE 3 '
'XTITLEpaper) OR (XTITLEan PHRASE 3 '
'XTITLEinfamous PHRASE 3 XTITLEarticle)))))')
'Xapian::Query(('
'(Zwhi OR why) AND (<alldocuments> AND_NOT '
'((XTITLE^ PHRASE 5 XTITLEa PHRASE 5 XTITLEfamous PHRASE 5 '
'XTITLEpaper PHRASE 5 XTITLE$) OR (XTITLE^ PHRASE 5 '
'XTITLEan PHRASE 5 XTITLEinfamous PHRASE 5 '
'XTITLEarticle PHRASE 5 XTITLE$)))))')
def test_build_query_in_filter_datetime(self):
self.sq.add_filter(SQ(content='why'))

View file

@ -342,7 +342,7 @@ class XapianSearchBackend(BaseSearchBackend):
termpos = add_text(termpos, prefix, term, weight)
elif field['type'] == 'datetime':
termpos = add_datetime_to_document(termpos, prefix, term, weight)
if term != "":
elif term != "":
# all other terms are added without positional information
add_to_document(prefix, term, weight)