Refactored some of the comon bits of query generation for phrase, all, and term based queries. Fixed 'in' based queries

This commit is contained in:
David Sauve 2009-12-01 08:58:34 -05:00
parent f027e26644
commit 09c12d88f7
2 changed files with 60 additions and 42 deletions

View File

@ -120,16 +120,21 @@ class XapianSearchQueryTestCase(TestCase):
# self.sq.add_filter(SQ(id__in=[1, 2, 3]))
# self.assertEqual(self.sq.build_query().get_description(), 'Xapian::Query(why AND pub_date:[* TO "2009-02-10 01:59:00"] AND author:{daniel TO *} AND created:{* TO "2009-02-12 12:13:00"} AND title:[B TO *] AND (id:"1" OR id:"2" OR id:"3"))')
def test_build_query_in_filter_single_words(self):
self.sq.add_filter(SQ(content='why'))
self.sq.add_filter(SQ(title__in=["Dune", "Jaws"]))
self.assertEqual(self.sq.build_query().get_description(), 'Xapian::Query((why AND (XTITLEdune OR XTITLEjaws)))')
def test_build_query_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(self.sq.build_query().get_description(), 'Xapian::Query((why AND (XTITLEa famous paper OR XTITLEan infamous article)))')
self.assertEqual(self.sq.build_query().get_description(), 'Xapian::Query((why AND ((XTITLEa PHRASE 3 XTITLEfamous PHRASE 3 XTITLEpaper) OR (XTITLEan PHRASE 3 XTITLEinfamous PHRASE 3 XTITLEarticle))))')
# 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(self.sq.build_query().get_description(), 'Xapian::Query((why AND_NOT (XTITLEa famous paper OR XTITLEan infamous article)))')
#
# def test_build_query_in_filter_datetime(self):
# self.sq.add_filter(SQ(content='why'))
# self.sq.add_filter(SQ(pub_date__in=[datetime.datetime(2009, 7, 6, 1, 56, 21)]))

View File

@ -952,19 +952,7 @@ class SearchQuery(BaseSearchQuery):
elif filter_type == 'startswith':
pass
elif filter_type == 'in':
query_list.append(
xapian.Query(
xapian.Query.OP_OR, [
xapian.Query(
'%s%s%s' % (
DOCUMENT_CUSTOM_TERM_PREFIX,
field.upper(),
_marshal_value(possible_value)
)
) for possible_value in value
]
)
)
query_list.append(self._filter_in(value, field, is_not))
if search_node.connector == 'OR':
@ -976,50 +964,75 @@ class SearchQuery(BaseSearchQuery):
if ' ' in value:
if is_not:
return xapian.Query(
xapian.Query.OP_AND_NOT,
xapian.Query(''),
xapian.Query
(xapian.Query.OP_PHRASE, value.split()
)
)
xapian.Query.OP_AND_NOT, self._all_query(), self._phrase_query(value.split())
)
else:
return xapian.Query(xapian.Query.OP_PHRASE, value.split())
return self._phrase_query(value.split())
else:
if is_not:
return xapian.Query(xapian.Query.OP_AND_NOT, '', value)
return xapian.Query(xapian.Query.OP_AND_NOT, self._all_query(), self._term_query(value))
else:
return xapian.Query(value)
return self._term_query(value)
def _filter_exact(self, value, field, is_not):
if ' ' in value:
phrase_query = xapian.Query(
xapian.Query.OP_PHRASE, [
'%s%s%s' % (
DOCUMENT_CUSTOM_TERM_PREFIX, field.upper(), _marshal_value(term)
) for term in value.split()
]
)
if is_not:
return xapian.Query(
xapian.Query.OP_AND_NOT, xapian.Query(''), phrase_query
xapian.Query.OP_AND_NOT, self._all_query(), self._phrase_query(value.split(), field)
)
else:
return phrase_query
return self._phrase_query(value.split(), field)
else:
term = '%s%s%s' % (
DOCUMENT_CUSTOM_TERM_PREFIX, field.upper(), value
)
if is_not:
return xapian.Query(xapian.Query.OP_AND_NOT, '', term)
return xapian.Query(xapian.Query.OP_AND_NOT, self._all_query(), self._term_query(value, field))
else:
return xapian.Query(term)
return self._term_query(value, field)
def _filter_in(self, value_list, field, is_not):
query_list = []
for value in value_list:
if ' ' in value:
query_list.append(
xapian.Query(
xapian.Query.OP_OR, self._phrase_query(value.split(), field)
)
)
else:
query_list.append(
xapian.Query(
xapian.Query.OP_OR, self._term_query(value, field)
)
)
return xapian.Query(xapian.Query.OP_OR, query_list)
def _all_query(self):
return xapian.Query('')
def _term_query(self, value, field=None):
if field:
return xapian.Query('%s%s%s' % (
DOCUMENT_CUSTOM_TERM_PREFIX, field.upper(), _marshal_value(value)
)
)
else:
return xapian.Query(value)
def _phrase_query(self, value_list, field=None):
if field:
return xapian.Query(
xapian.Query.OP_PHRASE, [
'%s%s%s' % (
DOCUMENT_CUSTOM_TERM_PREFIX, field.upper(), _marshal_value(value)
) for value in value_list
]
)
else:
return xapian.Query(xapian.Query.OP_PHRASE, value_list)
def _marshal_value(value):
"""
Private method that converts Python values to a string for Xapian values.
Private utility method that converts Python values to a string for Xapian values.
"""
if isinstance(value, datetime.datetime):
if value.microsecond: