MySQL使用全文索引(ngram解析器)对中文进行检索

在MySQL 5.6版本以前,只有MyISAM存储引擎支持全文引擎,

在5.6版本中,InnoDB加入了对全文索引的支持,但是不支持中文全文索引,

在5.7.6版本,MySQL内置了ngram全文解析器,用来支持亚洲语种的分词,

在使用前请确认自己的mysql版本, 可以使用 select version() 查看mysql的版本。

第一步,设置分词个数

ngram就是一段文字里面连续的n个字的序列。

ngram全文解析器能够对文本进行分词,每个单词是连续的n个字的序列。

例如,用ngram全文解析器对“生日快乐”进行分词, n = 几,就是将几个字按照一个词来分组:

n=1: '生', '日', '快', '乐' 
n=2: '生日', '日快', '快乐' 
n=3: '生日快', '日快乐' 
n=4: '生日快乐'

MySQL 中使用全局变量ngram_token_size来配置ngram中n的大小,它的取值范围是1到10,默认值是2。

通常ngram_token_size设置为要查询的单词的最小字数。

如果需要搜索单字,就要把ngram_token_size设置为1。

在默认值是2的情况下,搜索单字是得不到任何结果的。

因为中文单词最少是两个汉字,推荐使用默认值2。

ngram_token_size的两种设置方法:

#1. 启动mysqld命令时
mysqld --ngram_token_size=2

#2. 修改MySQL配置文件 (/etc/my.cnf) 修改配置文件后需要重启mysql
[mysqld] 
ngram_token_size=2

第二步,为字段建立全文索引

1. create table 建立

        FULLTEXT KEY `ext_info` (`ext_info`) WITH PARSER `ngram` 

CREATE TABLE `hello` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `real_name` varchar(50) COLLATE utf8mb4_bin DEFAULT NULL,
  `ext_info` varchar(2000) COLLATE utf8mb4_bin DEFAULT NULL,
  PRIMARY KEY (`id`),
  FULLTEXT KEY `ext_info` (`ext_info`) WITH PARSER `ngram` 
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;

2. 通过 alter table 建立

ALTER TABLE hello ADD FULLTEXT INDEX ext_info (ext_info) WITH PARSER ngram;

3. 通过 create index 建立

CREATE FULLTEXT INDEX ext_info ON hello (ext_info) WITH PARSER ngram;

第三步,开始检索

        表中有如下两条数据:

        

        使用SQL检索:select * from hello where match(ext_info) against('你') ,match中是你要检索的字段,against是要检索的内容,根据下面几个结果,可以看到已经检索到了我们想要的结果,

全文检索模式

全文索引检索有两种方式

1、自然语言模式(NATURAL LANGUAGE MODE) 


        自然语言模式是MySQL 默认的全文检索模式,也就是我们上方第三步搜索时,并没有指定使用哪种模式,默认就是自然语言模式,自然语言模式不能使用操作符,不能指定关键词必须出现或者必须不能出现等复杂查询,类似like。


2、BOOLEAN模式(BOOLEAN MODE)


        BOOLEAN模式可以使用操作符,可以支持指定关键词必须出现或者必须不能出现或者关键词的权重高还是低等复杂查询。

指定搜索模式

        

        指定搜索模式只需要在sql的against函数中增加一句指定的模式就好,这里指定为自然语言模式 (IN NATURAL LANGUAGE MODE) ,如下:

 select * from hello where match(ext_info) against('呀' IN NATURAL LANGUAGE MODE)

       

        

        不加也可以,因为就是默认的

自然语言模式下的相关性打分

select * , match(ext_info) against('你好h' IN NATURAL LANGUAGE MODE ) as score from hello 

        将 match against 放到查询列中,并起一个 score 的别名,可以看到,显示出了一个数值,这个数值就是该文档匹配搜索条件的相关性打分,该值是一个非负数的值,如果是0的话,说明毫无相关性。

        

        如果将全文检索放到搜索条件中,检索出的结果将自动按照相关性打分进行降序排序,例如该结果 yyyy 的打分高一点,就排在了上面。

        也可以通过指定的方式,使用升序排序。

BOOLEAN模式高级查询

against ('+你' IN BOOLEAN MODE) , 意为内容中必须包括你这个字。

select * from hello where match(ext_info) against ('+你' IN BOOLEAN MODE)

against ('+你 -好' IN BOOLEAN MODE) ,意为内容中必须有你这个字,但不能有好这个字。

select * from hello where match(ext_info) against ('+你 -好' IN BOOLEAN MODE)

下面的例子演示了BOOLEAN模式下运算符的使用方式:

'apple banana' 
无操作符,表示或,要么包含apple,要么包含banana

'+apple +juice'
必须同时包含两个词

'+apple macintosh'
必须包含apple,但是如果也包含macintosh的话,相关性会更高。

'+apple -macintosh'
必须包含apple,同时不能包含macintosh。

'+apple ~macintosh'
必须包含apple,但是如果也包含macintosh的话,相关性要比不包含macintosh的记录低。

'+apple +(>juice <pie)'
查询必须包含apple和juice或者apple和pie的记录,但是apple juice的相关性要比apple pie高。

'apple*'
查询包含以apple开头的单词的记录,如apple、apples、applet。

'"some words"'
使用双引号把要搜素的词括起来,效果类似于like '%some words%',
例如“some words of wisdom”会被匹配到,而“some noise words”就不会被匹配。

注意


1. 只能在类型为CHAR、VARCHAR或者TEXT的字段上创建全文索引。

2. 全文索引只支持InnoDB和MyISAM引擎。

3. MATCH (columnName) AGAINST ('keywords')。MATCH()函数使用的字段名,必须要与创建全文索引时指定的字段名一致。

4. MATCH()函数使用的字段名只能是同一个表的字段,因为全文索引不能够跨多个表进行检索。
如果要导入大数据集,使用先导入数据再在表上创建全文索引的方式要比先在表上创建全文索引再导入数据的方式快很多,所以全文索引是很影响TPS的。


版权声明:本文为cainiao1412原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。