From 29074178979697170bbc697cdc9820bfa85cc66c Mon Sep 17 00:00:00 2001 From: Dave Hall Date: Mon, 29 Aug 2011 19:18:27 +0100 Subject: [PATCH] Improving ranking behaviour for MySQL backend. --- src/watson/backends.py | 25 +++++++++++++++++++------ src/watson/tests.py | 6 +++--- 2 files changed, 22 insertions(+), 9 deletions(-) diff --git a/src/watson/backends.py b/src/watson/backends.py index 54c1b0b..be2dda6 100644 --- a/src/watson/backends.py +++ b/src/watson/backends.py @@ -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",), ) diff --git a/src/watson/tests.py b/src/watson/tests.py index 7ea0ad3..c469f02 100644 --- a/src/watson/tests.py +++ b/src/watson/tests.py @@ -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"] )