10月11, 2022
收藏本站

MySQL全文索引-ngram中文模糊搜索

说明:本文仅临时备注下,详情自行阅读官网:https://dev.mysql.com/doc/refman/5.7/en/fulltext-search-ngram.html

版本要求:MySQL 5.7.6后内置ngram全文解析器,用来支持中日韩分词。

# 查看当前mysql是否支持(有返回结果说明支持,值为2表示检索的字符至少要2个)
root test>show global variables like 'ngram_token_size';
+------------------+-------+
| Variable_name    | Value |
+------------------+-------+
| ngram_token_size | 2     |
+------------------+-------+
1 row in set (0.00 sec)

创建全文索引

语法:FULLTEXT (列名,列名,...) WITH PARSER ngram

# 建表时创建全文索引
CREATE TABLE articles (
      id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,
      title VARCHAR(200),
      body TEXT,
      FULLTEXT (title,body) WITH PARSER ngram
) ENGINE=InnoDB CHARACTER SET utf8mb4;

# 建表后新增
ALTER TABLE articles ADD FULLTEXT INDEX ft_title(title) with parser ngram;

使用

全文检索模式
常用的全文检索模式有两种:

  1. 自然语言模式(NATURAL LANGUAGE MODE) - 默认
    自然语言模式是MySQL 默认的全文检索模式。自然语言模式不能使用操作符,不能指定关键词必须出现或者必须不能出现等复杂查询。
  2. BOOLEAN模式(BOOLEAN MODE) - 完全匹配
    BOOLEAN模式可以使用操作符,可以支持指定关键词必须出现或者必须不能出现或者关键词的权重高还是低等复杂查询。

之前使用的时候没注意到还有boolean模式,导致之前使用全文索引发现搜索出不相关的结果,就放弃了,今天重新测试,使用boolean可以符合要求,如下。

# 搜索的字符前添加+,表示必须包含,后面添加IN BOOLEAN MODE
SELECT id,title,body
FROM articles
WHERE MATCH (title) 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”就不会被匹配。

注意

  • 只能在类型为CHAR、VARCHAR或者TEXT的字段上创建全文索引。
  • 全文索引只支持InnoDB和MyISAM引擎。
  • MATCH (columnName) AGAINST ('keywords')。
    MATCH()函数使用的字段名,必须要与创建全文索引时指定的字段名一致。如上面的示例,MATCH (title,body)使用的字段名与全文索引ft_articles(title,body)定义的字段名一致。如果要对title或者body字段分别进行查询,就需要在title和body字段上分别创建新的全文索引。
  • MATCH()函数使用的字段名只能是同一个表的字段,因为全文索引不能够跨多个表进行检索。
  • 如果要导入大数据集,使用先导入数据再在表上创建全文索引的方式要比先在表上创建全文索引再导入数据的方式快很多,所以全文索引是很影响TPS的。

Comments