如何在InnoDB全文索引上获得部分匹配单词搜索的不同分数?

时间:2018-01-16 15:14:19

标签: mysql full-text-search innodb

我在带有InnoDB全文索引的MySQL 5.6中获得了下表。

CREATE TABLE `blacklist_entries` (
  `blacklist_entry_id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(100) NOT NULL,
  `insertat` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`blacklist_entry_id`),
  FULLTEXT KEY `ftk_b_n` (`name`)
) ENGINE=InnoDB AUTO_INCREMENT=660004 DEFAULT CHARSET=utf8

这是我们正在处理的数据。 name中的所有条目都是单个字词,有时带有-,但不会超过一个字。

mysql> select * from blacklist_entries where name like '%battle%';
+--------------------+---------------------+---------------------+
| blacklist_entry_id | name                | insertat            |
+--------------------+---------------------+---------------------+
|               4159 | battleground        | 2018-01-16 12:15:46 |
|             604218 | battle              | 2018-01-16 12:18:59 |
|             604219 | battlefield         | 2018-01-16 12:18:59 |
|             604220 | battlefields        | 2018-01-16 12:18:59 |
|             604221 | battles             | 2018-01-16 12:18:59 |
|             660003 | abcbattle           | 2018-01-16 12:49:34 |
+--------------------+---------------------+---------------------+

我想创建一个全文搜索此列表,该列表能够按相关性排序,其中完整匹配的得分高于部分匹配。

当我运行此查询时

select
    *,match(name) against ('battle battle* *battle' IN BOOLEAN MODE) as score
from blacklist_entries where match(name)
    against ('battle battle* *battle' IN BOOLEAN MODE);

我得到以下结果。

+--------+---------------------+---------------------+--------------------+
|     id | name                | insertat            | score              |
+--------+---------------------+---------------------+--------------------+
|   4159 | battleground        | 2018-01-16 12:15:46 |  17.11724281311035 |
| 604218 | battle              | 2018-01-16 12:18:59 |  17.11724281311035 |
| 604219 | battlefield         | 2018-01-16 12:18:59 |  17.11724281311035 |
| 604220 | battlefields        | 2018-01-16 12:18:59 |  17.11724281311035 |
| 604221 | battles             | 2018-01-16 12:18:59 |  17.11724281311035 |
+--------+---------------------+---------------------+--------------------+

这有两个问题。

  • 所有结果都有相同的分数,即使是完全匹配
  • 它与右侧不匹配,缺少此行

    | 660003 | abcbattle           | 2018-01-16 12:49:34 |  17.11724281311035 |
    

我可以更改查询中的某些内容以说服MySQL对这些匹配进行不同的评分吗?

如果那是不可能的,是否有可行的替代方案,比如在存储过程中实现我自己的评分,并再次迭代完整列表以至少确定完全匹配以将其排名更高?

如果这些都不起作用,我将不得不在我的应用层完全建立评分。显然这会花费额外的资源,所以我想避免这种情况。

2 个答案:

答案 0 :(得分:1)

https://dev.mysql.com/doc/refman/5.6/en/fulltext-boolean.html

分数是单词出现的时间量,因此对于所有单词,它会出现一次并将结果分开。

答案 1 :(得分:1)

MATCH(name) AGAINST('battle*' IN BOOLEAN MODE)
    + 0.0001 * (name = 'battle')  AS score

这应匹配示例中的所有单词,然后稍微提升完全匹配。

如果在文本字段中间找到单词时进行提升:

   + 0.0001 * (REGEXP '[[:<:]]battle[[:>:]]')

0.0001没有什么特别之处;它足以改变分数,但不会大到改变&#34;结果&#34 ;.