diff --git a/tests/xapian_backend.py b/tests/xapian_backend.py index 32ad84e..15362e8 100644 --- a/tests/xapian_backend.py +++ b/tests/xapian_backend.py @@ -281,6 +281,16 @@ class XapianSearchBackendTestCase(TestCase): results = self.sb.search('*', sort_by=['flag', '-id']) self.assertEqual([result.pk for result in results['results']], [2, 3, 1]) + def test_boost(self): + self.sb.update(self.msi, self.sample_objs) + + # TODO: Need a better test case here. Possibly better test data? + results = self.sb.search('*', boost={'true': 2}) + self.assertEqual([result.pk for result in results['results']], [1, 3, 2]) + + results = self.sb.search('*', boost={'true': 1.5}) + self.assertEqual([result.pk for result in results['results']], [1, 3, 2]) + def test__marshal_value(self): self.assertEqual(self.sb._marshal_value('abc'), u'abc') self.assertEqual(self.sb._marshal_value(1), '\xa0') diff --git a/tests/xapian_query.py b/tests/xapian_query.py index 83338dd..65f2e94 100644 --- a/tests/xapian_query.py +++ b/tests/xapian_query.py @@ -80,11 +80,6 @@ class XapianSearchQueryTestCase(TestCase): self.sq.add_filter('content', 'hello world') self.assertEqual(self.sq.build_query(), '"hello world"') - # def test_build_query_boost(self): - # self.sq.add_filter('content', 'hello') - # self.sq.add_boost('world', 5) - # self.assertEqual(self.sq.build_query(), "hello world^5") - # 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)) diff --git a/xapian_backend.py b/xapian_backend.py index a21476f..dd73266 100644 --- a/xapian_backend.py +++ b/xapian_backend.py @@ -247,7 +247,7 @@ class SearchBackend(BaseSearchBackend): def search(self, query_string, sort_by=None, start_offset=0, end_offset=DEFAULT_MAX_RESULTS, fields='', highlight=False, facets=None, date_facets=None, query_facets=None, - narrow_queries=None, **kwargs): + narrow_queries=None, boost=None, **kwargs): """ Executes the search as defined in `query_string`. @@ -264,6 +264,7 @@ class SearchBackend(BaseSearchBackend): `date_facets` -- Facet results on date ranges (default = None) `query_facets` -- Facet results on queries (default = None) `narrow_queries` -- Narrow queries (default = None) + `boost` -- Dictionary of terms and weights to boost results Returns: A dictionary with the following keys: @@ -305,7 +306,9 @@ class SearchBackend(BaseSearchBackend): warnings.warn("Query faceting has not been implemented yet.", Warning, stacklevel=2) database = self._database() - query, spelling_suggestion = self._query(database, query_string, narrow_queries) + query, spelling_suggestion = self._query( + database, query_string, narrow_queries, boost + ) enquire = self._enquire(database, query) if sort_by: @@ -535,7 +538,7 @@ class SearchBackend(BaseSearchBackend): term_generator.set_document(document) return term_generator - def _query(self, database, query_string, narrow_queries=None): + def _query(self, database, query_string, narrow_queries=None, boost=None): """ Private method that takes a query string and returns a xapian.Query. @@ -544,6 +547,7 @@ class SearchBackend(BaseSearchBackend): Optional arguments: `narrow_queries` -- A list of queries to narrow the query with + `boost` -- A dictionary of terms to boost with values Returns a xapian.Query instance with prefixes and ranges properly setup as pulled from the `query_string`. @@ -569,6 +573,16 @@ class SearchBackend(BaseSearchBackend): xapian.Query.OP_FILTER, query, xapian.Query(xapian.Query.OP_AND, subqueries) ) + if boost: + subqueries = [ + xapian.Query( + xapian.Query.OP_SCALE_WEIGHT, xapian.Query(term), value + ) for term, value in boost.iteritems() + ] + query = xapian.Query( + xapian.Query.OP_OR, query, + xapian.Query(xapian.Query.OP_AND, subqueries) + ) return query, spelling_suggestion @@ -772,17 +786,6 @@ class SearchQuery(BaseSearchQuery): else: final_query = query - # print final_query - - # TODO: Implement boost - # if self.boost: - # boost_list = [] - # - # for boost_word, boost_value in self.boost.items(): - # boost_list.append("%s^%s" % (boost_word, boost_value)) - # - # final_query = "%s %s" % (final_query, " ".join(boost_list)) - return final_query def run(self): @@ -814,6 +817,9 @@ class SearchQuery(BaseSearchQuery): if self.narrow_queries: kwargs['narrow_queries'] = self.narrow_queries + + if self.boost: + kwargs['boost'] = self.boost results = self.backend.search(final_query, **kwargs) self._results = results.get('results', [])