Fixed sorting by integer and added tests to prove it

This commit is contained in:
David Sauve 2009-07-09 14:04:06 -04:00
parent 1a35a91a47
commit 00892d695e
3 changed files with 29 additions and 4 deletions

View file

@ -7,6 +7,7 @@ class MockModel(models.Model):
user = models.CharField(max_length=255)
foo = models.CharField(max_length=255, blank=True)
pub_date = models.DateTimeField(default=datetime.datetime.now)
value = models.IntegerField()
def __unicode__(self):
return self.user

View file

@ -18,6 +18,7 @@ class XapianMockSearchIndex(indexes.SearchIndex):
text = indexes.CharField(document=True, use_template=True)
name = indexes.CharField(model_attr='author')
pub_date = indexes.DateField(model_attr='pub_date')
value = indexes.IntegerField(model_attr='value')
class XapianSearchSite(sites.SearchSite):
@ -44,6 +45,7 @@ class XapianSearchBackendTestCase(TestCase):
mock.id = i
mock.author = 'david%s' % i
mock.pub_date = datetime.date(2009, 2, 25) - datetime.timedelta(days=i)
mock.value = i * 5
self.sample_objs.append(mock)
def tearDown(self):
@ -87,7 +89,7 @@ class XapianSearchBackendTestCase(TestCase):
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', 'id': u'tests.mockmodel.1'}, {'name': u'david2', 'text': u'Indexed!\n2', 'pub_date': u'2009-02-23T00:00:00', 'id': u'tests.mockmodel.2'}, {'name': u'david3', 'text': u'Indexed!\n3', 'pub_date': u'2009-02-22T00:00:00', 'id': u'tests.mockmodel.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'}])
def test_remove(self):
self.sb.update(self.msi, self.sample_objs)
@ -95,7 +97,7 @@ class XapianSearchBackendTestCase(TestCase):
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', 'id': u'tests.mockmodel.2'}, {'name': u'david3', 'text': u'Indexed!\n3', 'pub_date': u'2009-02-22T00:00:00', 'id': u'tests.mockmodel.3'}])
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'}])
def test_clear(self):
self.sb.update(self.msi, self.sample_objs)
@ -197,6 +199,18 @@ class XapianSearchBackendTestCase(TestCase):
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'])
def test__from_python(self):
self.assertEqual(self.sb._from_python('abc'), u'abc')

View file

@ -114,7 +114,7 @@ class SearchBackend(BaseSearchBackend):
The document also contains a pickled version of the object itself in
the document data field.
Finally, the database itself maintains a list of all index field names
Also, the database itself maintains a list of all index field names
in use through the database meta data field with the name `schema`.
This is a pickled data that can be loaded on demand and used to assign
prefixes to query parsers so that a user can perform field name
@ -123,6 +123,12 @@ class SearchBackend(BaseSearchBackend):
`<field_name>:<value>`
eg.: `'foo:bar'` will filter based on the `foo` field for `bar`.
Finally, we also store field values to be used for sorting data. We
store these in the document value slots (position zero is reserver
for the document ID). All values are stored as unicode strings with
conversion of float, int, double, values being done by Xapian itself
through the use of the :method:xapian.sortable_serialise method.
"""
schema = self._build_schema()
@ -148,7 +154,11 @@ class SearchBackend(BaseSearchBackend):
data = self._from_python(value)
indexer.index_text(data)
indexer.index_text(data, 1, prefix)
document.add_value(i + 1, data)
if isinstance(value, (int, long, float)):
document.add_value(i + 1, xapian.sortable_serialise(value))
else:
document.add_value(i + 1, data)
document.set_data(pickle.dumps(document_data, pickle.HIGHEST_PROTOCOL))
document.add_term(DOCUMENT_ID_TERM_PREFIX + document_id)