MySQL:全文本和 Bool 文本检索
全文本检索
之前我们使用的通配符或正则表达式进行对关键字的检索,效果很好,但是还是有一些不足的。首先是这样的检索就需要对所有的行进行检索,那么当数据量过多时就会带来性能问题。第二是这样的检索都是完全匹配的,对于模糊查找或者是部分索引而言,没有很强大的功能。这个时候我们就需要更为智能的检索方式,一种不错的选择是使用全文本搜索。
全文本搜索有以下注意事项:
- 被添加入非用词列表的词和短词(默认 3 个字符及以下的词)将会被自动忽略;
- 某个词出现频率很高时将被自动添加入非用词列表;
- 检索的表中若行数少于 3 行,不返回任何结果;
- 词之间的单引号将被自动忽略,即 “ it's ” 将被认为是 “its”;
- MySQL 暂不支持临近操作符。
数据库的搜索基于对数据库引擎的使用,例如 MyISAM 和 InnoDB,但是并不是所有引擎都可以支持全文本检索,例如 InnoDB 引擎就不支持。
建立索引
所谓全文本搜索,并不是对全部的字段进行匹配,而是通过一种名为索引的功能。所谓索引就是在指定的列中指定一些词,用这些词构建一个索引,然后进行检索时就可以根据这些词进行更高效的检索。
在一张表被建立时,可以使用 FULLTEXT 子句启用全文本搜索。通过在该子句中指定构建检索的列,列的数量可以是多个,定义之后 MySQL 将会自动维护索引。当我需要全文本搜索时,就可以根据建立的检索进行匹配。检索可以在建表的时候进行指定,也可以在后续指定。值得一提的是导入数据时,数据的量是过多的,还没有根据需要进行管理。这个时候启用全本文检索的话,对维护检索的开销是很大的,因此全文本搜索应该避免在数据大量变动时启用。
ENGINE 则是用于指定这个表的搜索引擎。
进行搜索
要进行全文本搜索,就需要使用 Match() 函数和 Against() 函数进行联合工作。Match() 函数用于指定被搜索的列,其中指定的列必须已经被 FULLTEXT 子句所建立检索,Against() 函数用于指定搜索的内容。
当然这个搜索也可以使用 LIKE 子句实现,不同在于全文本搜索更为智能。例如全文本搜索的结果会自动排序,例如可以按照检索词的出现位置的前后进行排序,这样对于数据的组织更为方便。这个功能的机理是什么?在全文本搜索时 Match() 函数和 Against() 函数会根据搜索的效果,通过一定的规则计算出一个值,用这个值来度量检索的相关度,依次决定是否回显和次序。
查询拓展
所谓查询拓展,也就是对一个关键字进行相关性查询,即使这个结果没有包含检索词,也能通过一定的规则判断是否相关。要实现这个功能,就需要基于全文本搜索找到所需要的数据,然后通过这些信息为参考进行一次新的全文本搜索,此时的结果将根据相关性返回更多信息。例如对于一次全文本搜索:
对其使用查询扩展,将会返回具有相关性的数据,例如复现的单词。
Bool 文本搜索
使用 布尔方式 (boolean mode) 可以使文本搜索能够附带更多信息,例如需要匹配的词、排斥的词、回显数据优先级等信息。由于这种方式比较精确,因此一般会结合全文本搜索来进行,保证效率。想要使用布尔方式,就需要加入关键字 IN BOOLEAN MODE。
布尔操作符
操作符 | 功能 |
---|---|
+ | 包含检索词 |
- | 排除检索词 |
> | 包含检索词并提高优先级 |
< | 包含检索词并减少优先级 |
() | 将词组成表达式 |
~ | 取消词的排序值 |
* | 词尾的通配符 |
"" | 定义短语 |
- 将被组成的表达式可以被包含、排除或排序。
实例
这个例子可以排除包含指定字符的所有行。
这个例子查找同时包含指定单词的所有行。
这个例子查找存在指定单词的所有行。
这个例子查找同时包含指定短语的所有行。
这个例子给定了指定单词的优先级。
这个例子查找了表达式。
参考资料
《MySQL Crash Course》[英] Ben Forta 著,刘晓霞 钟鸣 译,人民邮电出版社
菜鸟教程——MySQL 教程