Improving ranking behaviour for MySQL backend.

This commit is contained in:
Dave Hall 2011-08-29 19:18:27 +01:00
parent 1f51b094bd
commit 2907417897
2 changed files with 22 additions and 9 deletions

View file

@ -166,7 +166,7 @@ class PostgresSearchBackend(SearchBackend):
def escape_mysql_boolean_query(search_text):
return u" ".join(
u'+"{word}"'.format(
word = word,
word = word.replace(u'"', u''),
)
for word in search_text.split()
)
@ -188,8 +188,11 @@ class MySQLSearchBackend(SearchBackend):
cursor.execute("ALTER TABLE watson_searchentry ENGINE = MyISAM")
# Change the collaction to a case-insensitive one.
cursor.execute("ALTER TABLE watson_searchentry CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci")
# Add the full text index.
# Add the full text indexex.
cursor.execute("CREATE FULLTEXT INDEX watson_searchentry_fulltext ON watson_searchentry (title, description, content)")
cursor.execute("CREATE FULLTEXT INDEX watson_searchentry_title ON watson_searchentry (title)")
cursor.execute("CREATE FULLTEXT INDEX watson_searchentry_description ON watson_searchentry (description)")
cursor.execute("CREATE FULLTEXT INDEX watson_searchentry_content ON watson_searchentry (content)")
supports_ranking = True
@ -202,11 +205,16 @@ class MySQLSearchBackend(SearchBackend):
def do_search_ranking(self, engine_slug, queryset, search_text):
"""Performs full text ranking."""
search_text = escape_mysql_boolean_query(search_text)
return queryset.extra(
select = {
"watson_rank": "MATCH (title, description, content) AGAINST (%s IN BOOLEAN MODE)",
"watson_rank": """
((MATCH (title) AGAINST (%s IN BOOLEAN MODE)) * 3) +
((MATCH (description) AGAINST (%s IN BOOLEAN MODE)) * 2) +
((MATCH (content) AGAINST (%s IN BOOLEAN MODE)) * 1)
""",
},
select_params = (escape_mysql_boolean_query(search_text),),
select_params = (search_text, search_text, search_text,),
order_by = ("-watson_rank",),
)
@ -235,11 +243,16 @@ class MySQLSearchBackend(SearchBackend):
def do_filter_ranking(self, engine_slug, queryset, search_text):
"""Performs the full text ranking."""
search_text = escape_mysql_boolean_query(search_text)
return queryset.extra(
select = {
"watson_rank": "MATCH (watson_searchentry.title, watson_searchentry.description, watson_searchentry.content) AGAINST (%s IN BOOLEAN MODE)",
"watson_rank": """
((MATCH (watson_searchentry.title) AGAINST (%s IN BOOLEAN MODE)) * 3) +
((MATCH (watson_searchentry.description) AGAINST (%s IN BOOLEAN MODE)) * 2) +
((MATCH (watson_searchentry.content) AGAINST (%s IN BOOLEAN MODE)) * 1)
""",
},
select_params = (escape_mysql_boolean_query(search_text),),
select_params = (search_text, search_text, search_text,),
order_by = ("-watson_rank",),
)

View file

@ -375,7 +375,7 @@ class RankingTest(SearchTestBase):
super(RankingTest, self).setUp()
self.test11.title += " fooo baar fooo"
self.test11.save()
self.test12.title += " fooo baar"
self.test12.content += " fooo baar"
self.test12.save()
def testRankingParamPresentOnSearch(self):
@ -394,14 +394,14 @@ class RankingTest(SearchTestBase):
def testRankingWithSearch(self):
self.assertEqual(
[entry.title for entry in watson.search("FOOO")],
[u"title model1 instance11 fooo baar fooo", u"title model1 instance12 fooo baar"]
[u"title model1 instance11 fooo baar fooo", u"title model1 instance12"]
)
@skipUnless(get_backend().supports_ranking, "search backend does not support ranking")
def testRankingWithFilter(self):
self.assertEqual(
[entry.title for entry in watson.filter(TestModel1, "FOOO")],
[u"title model1 instance11 fooo baar fooo", u"title model1 instance12 fooo baar"]
[u"title model1 instance11 fooo baar fooo", u"title model1 instance12"]
)