mirror of
https://github.com/Hopiu/xapian-haystack.git
synced 2026-05-16 11:03:17 +00:00
Started work in refactor
This commit is contained in:
parent
ed902475b9
commit
74adafe2b6
3 changed files with 82 additions and 106 deletions
|
|
@ -18,4 +18,4 @@ import warnings
|
|||
warnings.simplefilter('ignore', Warning)
|
||||
|
||||
from xapian_tests.tests.xapian_query import *
|
||||
from xapian_tests.tests.xapian_backend import *
|
||||
# from xapian_tests.tests.xapian_backend import *
|
||||
|
|
|
|||
|
|
@ -50,78 +50,78 @@ class XapianSearchQueryTestCase(TestCase):
|
|||
super(XapianSearchQueryTestCase, self).tearDown()
|
||||
|
||||
def test_build_query_all(self):
|
||||
self.assertEqual(self.sq.build_query(), '*')
|
||||
|
||||
self.assertEqual(self.sq.build_query().get_description(), 'Xapian::Query(<alldocuments>)')
|
||||
|
||||
def test_build_query_single_word(self):
|
||||
self.sq.add_filter(SQ(content='hello'))
|
||||
self.assertEqual(self.sq.build_query(), 'hello')
|
||||
|
||||
self.assertEqual(self.sq.build_query().get_description(), 'Xapian::Query(hello)')
|
||||
|
||||
def test_build_query_multiple_words_and(self):
|
||||
self.sq.add_filter(SQ(content='hello'))
|
||||
self.sq.add_filter(SQ(content='world'))
|
||||
self.assertEqual(self.sq.build_query(), '(hello AND 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(), '(NOT (hello) AND NOT (world))')
|
||||
|
||||
def test_build_query_multiple_words_or(self):
|
||||
self.sq.add_filter(SQ(content='hello'), use_or=True)
|
||||
self.sq.add_filter(SQ(content='world'), use_or=True)
|
||||
self.assertEqual(self.sq.build_query(), '(hello OR world)')
|
||||
|
||||
def test_build_query_multiple_words_mixed(self):
|
||||
self.sq.add_filter(SQ(content='why'))
|
||||
self.sq.add_filter(SQ(content='hello'), use_or=True)
|
||||
self.sq.add_filter(~SQ(content='world'))
|
||||
self.assertEqual(self.sq.build_query(), '((why OR hello) AND NOT (world))')
|
||||
|
||||
def test_build_query_phrase(self):
|
||||
self.sq.add_filter(SQ(content='hello world'))
|
||||
self.assertEqual(self.sq.build_query(), '"hello world"')
|
||||
|
||||
def test_build_query_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)))
|
||||
self.sq.add_filter(SQ(author__gt='david'))
|
||||
self.sq.add_filter(SQ(created__lt=datetime.datetime(2009, 2, 12, 12, 13)))
|
||||
self.sq.add_filter(SQ(title__gte='B'))
|
||||
self.sq.add_filter(SQ(id__in=[1, 2, 3]))
|
||||
self.assertEqual(self.sq.build_query(), '(why AND pub_date:..20090210015900 AND NOT author:..david AND NOT created:20090212121300..* AND title:B..* AND (id:1 OR id:2 OR id:3))')
|
||||
|
||||
def test_build_query_multiple_exclude_types(self):
|
||||
self.sq.add_filter(~SQ(content='why'))
|
||||
self.sq.add_filter(~SQ(pub_date__lte=datetime.datetime(2009, 2, 10, 1, 59)))
|
||||
self.sq.add_filter(~SQ(author__gt='david'))
|
||||
self.sq.add_filter(~SQ(created__lt=datetime.datetime(2009, 2, 12, 12, 13)))
|
||||
self.sq.add_filter(~SQ(title__gte='B'))
|
||||
self.sq.add_filter(~SQ(id__in=[1, 2, 3]))
|
||||
self.assertEqual(self.sq.build_query(), '(NOT (why) AND NOT (pub_date:..20090210015900) AND NOT (NOT author:..david) AND NOT (NOT created:20090212121300..*) AND NOT (title:B..*) AND NOT ((id:1 OR id:2 OR id:3)))')
|
||||
|
||||
def test_build_query_wildcard_filter_types(self):
|
||||
self.sq.add_filter(SQ(content='why'))
|
||||
self.sq.add_filter(SQ(title__startswith='haystack'))
|
||||
self.assertEqual(self.sq.build_query(), '(why AND title:haystack*)')
|
||||
|
||||
def test_clean(self):
|
||||
self.assertEqual(self.sq.clean('hello world'), 'hello world')
|
||||
self.assertEqual(self.sq.clean('hello AND world'), 'hello and world')
|
||||
self.assertEqual(self.sq.clean('hello AND OR NOT + - && || ! ( ) { } [ ] ^ " ~ * ? : \ world'), 'hello and or not \\+ \\- \\&& \\|| \\! \\( \\) \\{ \\} \\[ \\] \\^ \\" \\~ \\* \\? \\: \\\\ world')
|
||||
self.assertEqual(self.sq.clean('so please NOTe i am in a bAND and bORed'), 'so please NOTe i am in a bAND and bORed')
|
||||
|
||||
def test_build_query_with_models(self):
|
||||
self.sq.add_filter(SQ(content='hello'))
|
||||
self.sq.add_model(MockModel)
|
||||
self.assertEqual(self.sq.build_query(), u'(hello) AND (django_ct:core.mockmodel)')
|
||||
|
||||
self.sq.add_model(AnotherMockModel)
|
||||
self.assertEqual(self.sq.build_query(), u'(hello) AND (django_ct:core.anothermockmodel OR django_ct:core.mockmodel)')
|
||||
|
||||
def test_build_query_with_datetime(self):
|
||||
self.sq.add_filter(SQ(pub_date=datetime.datetime(2009, 5, 9, 16, 20)))
|
||||
self.assertEqual(self.sq.build_query(), u'pub_date:20090509162000')
|
||||
|
||||
def test_build_query_with_sequence_and_filter_not_in(self):
|
||||
self.sq.add_filter(SQ(id__exact=[1, 2, 3]))
|
||||
self.assertEqual(self.sq.build_query(), u'id:[1, 2, 3]')
|
||||
self.assertEqual(self.sq.build_query().get_description(), 'Xapian::Query((NOT hello NOT world))')
|
||||
|
||||
# def test_build_query_multiple_words_or(self):
|
||||
# self.sq.add_filter('content', 'hello', use_or=True)
|
||||
# self.sq.add_filter('content', 'world', use_or=True)
|
||||
# self.assertEqual(self.sq.build_query(), 'hello OR world')
|
||||
#
|
||||
# def test_build_query_multiple_words_mixed(self):
|
||||
# self.sq.add_filter('content', 'why')
|
||||
# self.sq.add_filter('content', 'hello', use_or=True)
|
||||
# self.sq.add_filter('content', 'world', use_not=True)
|
||||
# self.assertEqual(self.sq.build_query(), 'why OR hello NOT world')
|
||||
#
|
||||
# def test_build_query_phrase(self):
|
||||
# self.sq.add_filter('content', 'hello world')
|
||||
# self.assertEqual(self.sq.build_query(), '"hello world"')
|
||||
#
|
||||
# def test_build_query_multiple_filter_types(self):
|
||||
# self.sq.add_filter('content', 'why')
|
||||
# self.sq.add_filter('pub_date__lte', datetime.datetime(2009, 2, 10, 1, 59))
|
||||
# self.sq.add_filter('author__gt', 'david')
|
||||
# self.sq.add_filter('created__lt', datetime.datetime(2009, 2, 12, 12, 13))
|
||||
# self.sq.add_filter('title__gte', 'B')
|
||||
# self.sq.add_filter('id__in', [1, 2, 3])
|
||||
# self.assertEqual(self.sq.build_query(), 'why AND pub_date:..20090210015900 AND NOT author:..david AND NOT created:20090212121300..* AND title:B..* AND (id:1 OR id:2 OR id:3)')
|
||||
#
|
||||
# def test_build_query_multiple_exclude_types(self):
|
||||
# self.sq.add_filter('content', 'why', use_not=True)
|
||||
# self.sq.add_filter('pub_date__lte', datetime.datetime(2009, 2, 10, 1, 59), use_not=True)
|
||||
# self.sq.add_filter('author__gt', 'david', use_not=True)
|
||||
# self.sq.add_filter('created__lt', datetime.datetime(2009, 2, 12, 12, 13), use_not=True)
|
||||
# self.sq.add_filter('title__gte', 'B', use_not=True)
|
||||
# self.sq.add_filter('id__in', [1, 2, 3], use_not=True)
|
||||
# self.assertEqual(self.sq.build_query(), 'NOT why AND NOT pub_date:..20090210015900 AND author:..david AND created:20090212121300..* AND NOT title:B..* AND NOT id:1 NOT id:2 NOT id:3')
|
||||
#
|
||||
# def test_build_query_wildcard_filter_types(self):
|
||||
# self.sq.add_filter('content', 'why')
|
||||
# self.sq.add_filter('title__startswith', 'haystack')
|
||||
# self.assertEqual(self.sq.build_query(), 'why AND title:haystack*')
|
||||
#
|
||||
# def test_clean(self):
|
||||
# self.assertEqual(self.sq.clean('hello world'), 'hello world')
|
||||
# self.assertEqual(self.sq.clean('hello AND world'), 'hello and world')
|
||||
# self.assertEqual(self.sq.clean('hello AND OR NOT + - && || ! ( ) { } [ ] ^ " ~ * ? : \ world'), 'hello and or not \\+ \\- \\&& \\|| \\! \\( \\) \\{ \\} \\[ \\] \\^ \\" \\~ \\* \\? \\: \\\\ world')
|
||||
# self.assertEqual(self.sq.clean('so please NOTe i am in a bAND and bORed'), 'so please NOTe i am in a bAND and bORed')
|
||||
#
|
||||
# def test_build_query_with_models(self):
|
||||
# self.sq.add_filter('content', 'hello')
|
||||
# self.sq.add_model(MockModel)
|
||||
# self.assertEqual(self.sq.build_query(), u'(hello) django_ct:core.mockmodel')
|
||||
#
|
||||
# self.sq.add_model(AnotherMockModel)
|
||||
# self.assertEqual(self.sq.build_query(), u'(hello) django_ct:core.anothermockmodel django_ct:core.mockmodel')
|
||||
#
|
||||
# def test_build_query_with_datetime(self):
|
||||
# self.sq.add_filter('pub_date', datetime.datetime(2009, 5, 9, 16, 20))
|
||||
# self.assertEqual(self.sq.build_query(), u'pub_date:20090509162000')
|
||||
#
|
||||
# def test_build_query_with_sequence_and_filter_not_in(self):
|
||||
# self.sq.add_filter('id__exact', [1, 2, 3])
|
||||
# self.assertEqual(self.sq.build_query(), u'id:[1, 2, 3]')
|
||||
|
|
|
|||
|
|
@ -933,46 +933,22 @@ class SearchQuery(BaseSearchQuery):
|
|||
super(SearchQuery, self).__init__(backend=backend)
|
||||
self.backend = backend or SearchBackend()
|
||||
|
||||
def build_query_fragment(self, field, filter_type, value):
|
||||
"""
|
||||
Builds a search query fragment from a field, filter type and value.
|
||||
Returns:
|
||||
A query string fragment suitable for parsing by Xapian.
|
||||
"""
|
||||
result = ''
|
||||
def build_query(self):
|
||||
if not self.query_filter:
|
||||
return xapian.Query('')
|
||||
|
||||
if not isinstance(value, (list, tuple)):
|
||||
# Convert whatever we find to what xapian wants.
|
||||
value = self.backend._marshal_value(value)
|
||||
|
||||
# Check to see if it's a phrase for an exact match.
|
||||
if ' ' in value:
|
||||
value = '"%s"' % value
|
||||
|
||||
# 'content' is a special reserved word, much like 'pk' in
|
||||
# Django's ORM layer. It indicates 'no special field'.
|
||||
if field == 'content':
|
||||
result = value
|
||||
else:
|
||||
filter_types = {
|
||||
'exact': '%s:%s',
|
||||
'gte': '%s:%s..*',
|
||||
'gt': 'NOT %s:..%s',
|
||||
'lte': '%s:..%s',
|
||||
'lt': 'NOT %s:%s..*',
|
||||
'startswith': '%s:%s*',
|
||||
}
|
||||
|
||||
if filter_type != 'in':
|
||||
result = filter_types[filter_type] % (field, value)
|
||||
else:
|
||||
in_options = []
|
||||
for possible_value in value:
|
||||
in_options.append('%s:%s' % (field, possible_value))
|
||||
result = '(%s)' % ' OR '.join(in_options)
|
||||
|
||||
return result
|
||||
values = []
|
||||
|
||||
for child in self.query_filter.children:
|
||||
if isinstance(child, self.query_filter.__class__):
|
||||
print 'SQ: ', child # TODO: Recursive call down tree...
|
||||
else:
|
||||
expression, value = child
|
||||
field, filter_type = self.query_filter.split_expression(expression)
|
||||
values.append(value)
|
||||
|
||||
return xapian.Query(xapian.Query.OP_AND, values)
|
||||
|
||||
def run(self, spelling_query=None):
|
||||
"""
|
||||
Builds and executes the query. Returns a list of search results.
|
||||
|
|
|
|||
Loading…
Reference in a new issue