我在带有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对这些匹配进行不同的评分吗?
如果那是不可能的,是否有可行的替代方案,比如在存储过程中实现我自己的评分,并再次迭代完整列表以至少确定完全匹配以将其排名更高?
如果这些都不起作用,我将不得不在我的应用层完全建立评分。显然这会花费额外的资源,所以我想避免这种情况。
答案 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 ;.