Skip to content

Commit

Permalink
Implemented multi-field ordering on search
Browse files Browse the repository at this point in the history
  • Loading branch information
David Sauve committed Jul 9, 2009
1 parent a22442b commit ff0a466
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 15 deletions.
1 change: 1 addition & 0 deletions tests/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ class MockModel(models.Model):
foo = models.CharField(max_length=255, blank=True)
pub_date = models.DateTimeField(default=datetime.datetime.now)
value = models.IntegerField()
flag = models.BooleanField()

def __unicode__(self):
return self.user
Expand Down
22 changes: 15 additions & 7 deletions tests/xapian_backend.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ class XapianMockSearchIndex(indexes.SearchIndex):
name = indexes.CharField(model_attr='author')
pub_date = indexes.DateField(model_attr='pub_date')
value = indexes.IntegerField(model_attr='value')
flag = indexes.BooleanField(model_attr='flag')


class XapianSearchSite(sites.SearchSite):
Expand Down Expand Up @@ -46,6 +47,7 @@ def setUp(self):
mock.author = 'david%s' % i
mock.pub_date = datetime.date(2009, 2, 25) - datetime.timedelta(days=i)
mock.value = i * 5
mock.flag = bool(i % 2)
self.sample_objs.append(mock)

def tearDown(self):
Expand Down Expand Up @@ -89,15 +91,15 @@ def test_update(self):
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('')], [{'name': u'david1', 'text': u'Indexed!\n1', 'pub_date': u'2009-02-24T00:00:00', 'value': u'5', 'id': u'tests.mockmodel.1'}, {'name': u'david2', 'text': u'Indexed!\n2', 'pub_date': u'2009-02-23T00:00:00', 'value': u'10', 'id': u'tests.mockmodel.2'}, {'name': u'david3', 'text': u'Indexed!\n3', 'pub_date': u'2009-02-22T00:00:00', 'value': u'15', 'id': u'tests.mockmodel.3'}])
self.assertEqual([dict(doc) for doc in self.xapian_search('')], [{'flag': u'true', 'name': u'david1', 'text': u'Indexed!\n1', 'pub_date': u'2009-02-24T00:00:00', 'value': u'5', 'id': u'tests.mockmodel.1'}, {'flag': u'false', 'name': u'david2', 'text': u'Indexed!\n2', 'pub_date': u'2009-02-23T00:00:00', 'value': u'10', 'id': u'tests.mockmodel.2'}, {'flag': u'true', 'name': u'david3', 'text': u'Indexed!\n3', 'pub_date': u'2009-02-22T00:00:00', '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('')], [{'name': u'david2', 'text': u'Indexed!\n2', 'pub_date': u'2009-02-23T00:00:00', 'value': u'10', 'id': u'tests.mockmodel.2'}, {'name': u'david3', 'text': u'Indexed!\n3', 'pub_date': u'2009-02-22T00:00:00', 'value': u'15', 'id': u'tests.mockmodel.3'}])
self.assertEqual([dict(doc) for doc in self.xapian_search('')], [{'flag': u'false', 'name': u'david2', 'text': u'Indexed!\n2', 'pub_date': u'2009-02-23T00:00:00', 'value': u'10', 'id': u'tests.mockmodel.2'}, {'flag': u'true', 'name': u'david3', 'text': u'Indexed!\n3', 'pub_date': u'2009-02-22T00:00:00', 'value': u'15', 'id': u'tests.mockmodel.3'}])

def test_clear(self):
self.sb.update(self.msi, self.sample_objs)
Expand Down Expand Up @@ -178,7 +180,7 @@ def test_more_like_this(self):

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'2', u'3'])
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)
Expand All @@ -193,10 +195,10 @@ def test_delete_index(self):

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'])

Expand All @@ -205,13 +207,19 @@ def test_order_by(self):

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')
Expand Down
19 changes: 11 additions & 8 deletions xapian_backend.py
Original file line number Diff line number Diff line change
Expand Up @@ -305,16 +305,18 @@ def search(self, query_string, sort_by=None, start_offset=0, end_offset=DEFAULT_

enquire = xapian.Enquire(database)
enquire.set_query(query)
enquire.set_docid_order(enquire.ASCENDING)

if sort_by:
if len(sort_by) > 1:
raise SearchBackendError("Xapian does not handle more than one field for ordering.")
if sort_by[0].startswith('-'):
reverse = True
sort_by[0] = sort_by[0][1:] # Strip the '-'
else:
reverse = False
enquire.set_sort_by_relevance_then_value(schema.get(sort_by[0], -1) + 1, reverse)
sorter = xapian.MultiValueSorter()
for sort_field in sort_by:
if sort_field.startswith('-'):
reverse = False
sort_field = sort_field[1:] # Strip the '-'
else:
reverse = True # Reverse is inverted in Xapian -- http://trac.xapian.org/ticket/311
sorter.add(schema.get(sort_field, -1) + 1, reverse)
enquire.set_sort_by_key_then_relevance(sorter, True)

matches = enquire.get_mset(start_offset, end_offset)
results = self._process_results(matches, facets)
Expand Down Expand Up @@ -378,6 +380,7 @@ def more_like_this(self, model_instance):
)
enquire = xapian.Enquire(database)
enquire.set_query(query)
enquire.set_docid_order(enquire.DONT_CARE)
rset = xapian.RSet()
for match in enquire.get_mset(0, DEFAULT_MAX_RESULTS):
rset.add_document(match.get_docid())
Expand Down

0 comments on commit ff0a466

Please sign in to comment.