mirror of
https://github.com/Hopiu/xapian-haystack.git
synced 2026-03-16 22:20:31 +00:00
Fixed broken NOT query -- Thanks Supreet
This commit is contained in:
parent
21b60477e2
commit
d4c8c42275
3 changed files with 64 additions and 56 deletions
5
AUTHORS
5
AUTHORS
|
|
@ -3,9 +3,10 @@ Primary Authors:
|
|||
* David Sauve
|
||||
|
||||
|
||||
Thanks to
|
||||
Thanks to:
|
||||
* Daniel Lindsley for the awesome Haystack API and putting up with all
|
||||
of my questions.
|
||||
* Trapeze Media <http://www.trapeze.com/> for providing the time and
|
||||
resources to complete this project as well as Q&A.
|
||||
* Supreet Sethi for suggestions regarding morphologic date comparisons.
|
||||
* Supreet Sethi for suggestions regarding morphologic date comparisons and
|
||||
for fixing NOT query expressions.
|
||||
|
|
@ -29,18 +29,18 @@ class XapianSearchSite(sites.SearchSite):
|
|||
class XapianSearchBackendTestCase(TestCase):
|
||||
def setUp(self):
|
||||
super(XapianSearchBackendTestCase, self).setUp()
|
||||
|
||||
|
||||
temp_path = os.path.join('tmp', 'test_xapian_query')
|
||||
self.old_xapian_path = getattr(settings, 'HAYSTACK_XAPIAN_PATH', temp_path)
|
||||
settings.HAYSTACK_XAPIAN_PATH = temp_path
|
||||
|
||||
|
||||
self.site = XapianSearchSite()
|
||||
self.sb = SearchBackend(site=self.site)
|
||||
self.msi = XapianMockSearchIndex(MockModel, backend=self.sb)
|
||||
self.site.register(MockModel, XapianMockSearchIndex)
|
||||
|
||||
|
||||
self.sample_objs = []
|
||||
|
||||
|
||||
for i in xrange(1, 4):
|
||||
mock = MockModel()
|
||||
mock.id = i
|
||||
|
|
@ -49,19 +49,19 @@ class XapianSearchBackendTestCase(TestCase):
|
|||
mock.value = i * 5
|
||||
mock.flag = bool(i % 2)
|
||||
self.sample_objs.append(mock)
|
||||
|
||||
|
||||
def tearDown(self):
|
||||
if os.path.exists(settings.HAYSTACK_XAPIAN_PATH):
|
||||
index_files = os.listdir(settings.HAYSTACK_XAPIAN_PATH)
|
||||
|
||||
|
||||
for index_file in index_files:
|
||||
os.remove(os.path.join(settings.HAYSTACK_XAPIAN_PATH, index_file))
|
||||
|
||||
|
||||
os.removedirs(settings.HAYSTACK_XAPIAN_PATH)
|
||||
|
||||
|
||||
settings.HAYSTACK_XAPIAN_PATH = self.old_xapian_path
|
||||
super(XapianSearchBackendTestCase, self).tearDown()
|
||||
|
||||
|
||||
def xapian_search(self, query_string):
|
||||
database = xapian.Database(settings.HAYSTACK_XAPIAN_PATH)
|
||||
if query_string:
|
||||
|
|
@ -73,9 +73,9 @@ class XapianSearchBackendTestCase(TestCase):
|
|||
enquire = xapian.Enquire(database)
|
||||
enquire.set_query(query)
|
||||
matches = enquire.get_mset(0, DEFAULT_MAX_RESULTS)
|
||||
|
||||
|
||||
document_list = []
|
||||
|
||||
|
||||
for match in matches:
|
||||
document = match.get_document()
|
||||
object_data = pickle.loads(document.get_data())
|
||||
|
|
@ -83,155 +83,161 @@ class XapianSearchBackendTestCase(TestCase):
|
|||
object_data[key] = self.sb._from_python(value)
|
||||
object_data['id'] = force_unicode(document.get_value(0))
|
||||
document_list.append(object_data)
|
||||
|
||||
|
||||
return document_list
|
||||
|
||||
|
||||
def test_update(self):
|
||||
self.sb.update(self.msi, self.sample_objs)
|
||||
self.sb.update(self.msi, self.sample_objs) # Duplicates should be updated, not appended -- http://github.com/notanumber/xapian-haystack/issues/#issue/6
|
||||
|
||||
|
||||
self.assertEqual(len(self.xapian_search('')), 3)
|
||||
self.assertEqual([dict(doc) for doc in self.xapian_search('')], [{'flag': u't', 'name': u'david1', 'text': u'Indexed!\n1', 'pub_date': u'20090224000000', 'value': u'5', 'id': u'tests.mockmodel.1'}, {'flag': u'f', 'name': u'david2', 'text': u'Indexed!\n2', 'pub_date': u'20090223000000', 'value': u'10', 'id': u'tests.mockmodel.2'}, {'flag': u't', 'name': u'david3', 'text': u'Indexed!\n3', 'pub_date': u'20090222000000', 'value': u'15', 'id': u'tests.mockmodel.3'}])
|
||||
|
||||
|
||||
def test_remove(self):
|
||||
self.sb.update(self.msi, self.sample_objs)
|
||||
self.assertEqual(len(self.xapian_search('')), 3)
|
||||
|
||||
|
||||
self.sb.remove(self.sample_objs[0])
|
||||
self.assertEqual(len(self.xapian_search('')), 2)
|
||||
self.assertEqual([dict(doc) for doc in self.xapian_search('')], [{'flag': u'f', 'name': u'david2', 'text': u'Indexed!\n2', 'pub_date': u'20090223000000', 'value': u'10', 'id': u'tests.mockmodel.2'}, {'flag': u't', 'name': u'david3', 'text': u'Indexed!\n3', 'pub_date': u'20090222000000', 'value': u'15', 'id': u'tests.mockmodel.3'}])
|
||||
|
||||
|
||||
def test_clear(self):
|
||||
self.sb.update(self.msi, self.sample_objs)
|
||||
self.assertEqual(len(self.xapian_search('')), 3)
|
||||
|
||||
|
||||
self.sb.clear()
|
||||
self.assertEqual(len(self.xapian_search('')), 0)
|
||||
|
||||
|
||||
self.sb.update(self.msi, self.sample_objs)
|
||||
self.assertEqual(len(self.xapian_search('')), 3)
|
||||
|
||||
|
||||
self.sb.clear([AnotherMockModel])
|
||||
self.assertEqual(len(self.xapian_search('')), 3)
|
||||
|
||||
|
||||
self.sb.clear([MockModel])
|
||||
self.assertEqual(len(self.xapian_search('')), 0)
|
||||
|
||||
|
||||
self.sb.update(self.msi, self.sample_objs)
|
||||
self.assertEqual(len(self.xapian_search('')), 3)
|
||||
|
||||
|
||||
self.sb.clear([AnotherMockModel, MockModel])
|
||||
self.assertEqual(len(self.xapian_search('')), 0)
|
||||
|
||||
def test_search(self):
|
||||
self.sb.update(self.msi, self.sample_objs)
|
||||
self.assertEqual(len(self.xapian_search('')), 3)
|
||||
|
||||
|
||||
# Empty query
|
||||
self.assertEqual(self.sb.search(''), {'hits': 0, 'results': []})
|
||||
|
||||
# Wildcard -- All
|
||||
self.assertEqual(self.sb.search('*')['hits'], 3)
|
||||
self.assertEqual([result.pk for result in self.sb.search('*')['results']], [u'1', u'2', u'3'])
|
||||
|
||||
|
||||
# NOT operator
|
||||
self.assertEqual([result.pk for result in self.sb.search('NOT author:david1')['results']], [u'1', u'2', u'3'])
|
||||
|
||||
def test_field_facets(self):
|
||||
self.sb.update(self.msi, self.sample_objs)
|
||||
self.assertEqual(len(self.xapian_search('')), 3)
|
||||
|
||||
|
||||
self.assertEqual(self.sb.search('', facets=['name']), {'hits': 0, 'results': []})
|
||||
results = self.sb.search('index', facets=['name'])
|
||||
self.assertEqual(results['hits'], 3)
|
||||
self.assertEqual(results['facets']['fields']['name'], [('david1', 1), ('david2', 1), ('david3', 1)])
|
||||
|
||||
|
||||
# self.assertEqual(self.sb.search('', date_facets={'pub_date': {'start_date': datetime.date(2008, 2, 26), 'end_date': datetime.date(2008, 2, 26), 'gap': '/MONTH'}}), [])
|
||||
# results = self.sb.search('Index*', date_facets={'pub_date': {'start_date': datetime.date(2008, 2, 26), 'end_date': datetime.date(2008, 2, 26), 'gap': '/MONTH'}})
|
||||
# self.assertEqual(results['hits'], 3)
|
||||
# self.assertEqual(results['facets'], {})
|
||||
#
|
||||
#
|
||||
# self.assertEqual(self.sb.search('', query_facets={'name': '[* TO e]'}), [])
|
||||
# results = self.sb.search('Index*', query_facets={'name': '[* TO e]'})
|
||||
# self.assertEqual(results['hits'], 3)
|
||||
# self.assertEqual(results['facets'], {})
|
||||
|
||||
|
||||
def test_narrow_queries(self):
|
||||
self.sb.update(self.msi, self.sample_objs)
|
||||
self.assertEqual(len(self.xapian_search('')), 3)
|
||||
|
||||
|
||||
self.assertEqual(self.sb.search('', narrow_queries=['name:david1']), {'hits': 0, 'results': []})
|
||||
results = self.sb.search('index', narrow_queries=['name:david1'])
|
||||
self.assertEqual(results['hits'], 1)
|
||||
|
||||
|
||||
def test_highlight(self):
|
||||
self.sb.update(self.msi, self.sample_objs)
|
||||
self.assertEqual(len(self.xapian_search('')), 3)
|
||||
|
||||
|
||||
self.assertEqual(self.sb.search('', highlight=True), {'hits': 0, 'results': []})
|
||||
self.assertEqual(self.sb.search('Index', highlight=True)['hits'], 3)
|
||||
self.assertEqual([result.highlighted['text'] for result in self.sb.search('Index', highlight=True)['results']], ['<em>Index</em>ed!\n1', '<em>Index</em>ed!\n2', '<em>Index</em>ed!\n3'])
|
||||
|
||||
|
||||
def test_spelling_suggestion(self):
|
||||
self.sb.update(self.msi, self.sample_objs)
|
||||
self.assertEqual(len(self.xapian_search('')), 3)
|
||||
|
||||
|
||||
self.assertEqual(self.sb.search('indxe')['hits'], 0)
|
||||
self.assertEqual(self.sb.search('indxe')['spelling_suggestion'], 'indexed')
|
||||
|
||||
|
||||
self.assertEqual(self.sb.search('indxed')['hits'], 0)
|
||||
self.assertEqual(self.sb.search('indxed')['spelling_suggestion'], 'indexed')
|
||||
|
||||
|
||||
def test_stemming(self):
|
||||
self.sb.update(self.msi, self.sample_objs)
|
||||
self.assertEqual(len(self.xapian_search('')), 3)
|
||||
|
||||
|
||||
results = self.sb.search('index')
|
||||
self.assertEqual(results['hits'], 3)
|
||||
|
||||
|
||||
results = self.sb.search('indexing')
|
||||
self.assertEqual(results['hits'], 3)
|
||||
|
||||
|
||||
def test_more_like_this(self):
|
||||
self.sb.update(self.msi, self.sample_objs)
|
||||
self.assertEqual(len(self.xapian_search('')), 3)
|
||||
|
||||
|
||||
results = self.sb.more_like_this(self.sample_objs[0])
|
||||
self.assertEqual(results['hits'], 2)
|
||||
self.assertEqual([result.pk for result in results['results']], [u'3', u'2'])
|
||||
|
||||
|
||||
def test_document_count(self):
|
||||
self.sb.update(self.msi, self.sample_objs)
|
||||
self.assertEqual(self.sb.document_count(), 3)
|
||||
|
||||
|
||||
def test_delete_index(self):
|
||||
self.sb.update(self.msi, self.sample_objs)
|
||||
self.assert_(self.sb.document_count() > 0)
|
||||
|
||||
|
||||
self.sb.delete_index()
|
||||
self.assertEqual(self.sb.document_count(), 0)
|
||||
|
||||
|
||||
def test_order_by(self):
|
||||
self.sb.update(self.msi, self.sample_objs)
|
||||
|
||||
|
||||
results = self.sb.search('*', sort_by=['pub_date'])
|
||||
self.assertEqual([result.pk for result in results['results']], [u'1', u'2', u'3'])
|
||||
|
||||
|
||||
results = self.sb.search('*', sort_by=['-pub_date'])
|
||||
self.assertEqual([result.pk for result in results['results']], [u'3', u'2', u'1'])
|
||||
|
||||
|
||||
results = self.sb.search('*', sort_by=['id'])
|
||||
self.assertEqual([result.pk for result in results['results']], [u'3', u'2', u'1'])
|
||||
|
||||
|
||||
results = self.sb.search('*', sort_by=['-id'])
|
||||
self.assertEqual([result.pk for result in results['results']], [u'1', u'2', u'3'])
|
||||
|
||||
|
||||
results = self.sb.search('*', sort_by=['value'])
|
||||
self.assertEqual([result.pk for result in results['results']], [u'3', u'2', u'1'])
|
||||
|
||||
|
||||
results = self.sb.search('*', sort_by=['-value'])
|
||||
self.assertEqual([result.pk for result in results['results']], [u'1', u'2', u'3'])
|
||||
|
||||
|
||||
results = self.sb.search('*', sort_by=['flag', 'id'])
|
||||
self.assertEqual([result.pk for result in results['results']], [u'3', u'1', u'2'])
|
||||
|
||||
|
||||
results = self.sb.search('*', sort_by=['flag', '-id'])
|
||||
self.assertEqual([result.pk for result in results['results']], [u'1', u'3', u'2'])
|
||||
|
||||
|
||||
def test__from_python(self):
|
||||
self.assertEqual(self.sb._from_python('abc'), u'abc')
|
||||
self.assertEqual(self.sb._from_python(1), u'1')
|
||||
|
|
|
|||
|
|
@ -567,7 +567,8 @@ class SearchBackend(BaseSearchBackend):
|
|||
| xapian.QueryParser.FLAG_PHRASE \
|
||||
| xapian.QueryParser.FLAG_BOOLEAN \
|
||||
| xapian.QueryParser.FLAG_LOVEHATE \
|
||||
| xapian.QueryParser.FLAG_WILDCARD
|
||||
| xapian.QueryParser.FLAG_WILDCARD \
|
||||
| xapian.QueryParser.FLAG_PURE_NOT
|
||||
if getattr(settings, 'HAYSTACK_INCLUDE_SPELLING', False) is True:
|
||||
flags = flags | xapian.QueryParser.FLAG_SPELLING_CORRECTION
|
||||
return flags
|
||||
|
|
|
|||
Loading…
Reference in a new issue