摘要:在本教程中,您将学习如何使用 MySQL ngram 全文解析器来支持中文、日文、韩文等表意语言的全文搜索。
MySQL ngram 全文解析器简介
内置的 MySQL 全文解析器使用空格确定单词的开头和结尾。当涉及中文、日语和韩语等表意语言时,全文解析器有一个限制,即这些表意语言不使用单词分隔符。
为了解决这个问题,MySQL 提供了 ngram 全文解析器。从5.7.6版本开始,MySQL包含了ngram全文解析器作为内置服务器插件,这意味着MySQL会在MySQL数据库服务器启动时自动加载该插件。 MySQL 支持 InnoDB 和 MyISAM 存储引擎的 ngram 全文解析器。
根据定义,ngram 是文本序列中多个字符的连续序列。 ngram 全文解析器的主要功能是将文本序列标记为 n 个字符的连续序列。
下面说明了 ngram 全文解析器如何针对不同的 n 值标记文本序列:
n = 1: 'm','y','s','q','l'
n = 2: 'my', 'ys', 'sq','ql'
n = 3: 'mys', 'ysq', 'sql'
n = 4: 'mysq', 'ysql'
n = 5: 'mysql'
Code language: JavaScript (javascript)
使用 ngram 解析器创建FULLTEXT
索引
要创建使用 ngram 全文解析器的FULLTEXT
索引,请在CREATE TABLE
、 ALTER TABLE
或CREATE INDEX
语句中添加WITH PARSER ngram
。
考虑以下示例。
首先,创建新的posts
表,并将title
和body
列添加到使用 ngram 全文解析器的FULLTEXT
索引中。
DROP TABLE IF EXISTS posts;
CREATE TABLE posts (
id INT PRIMARY KEY AUTO_INCREMENT,
title VARCHAR(255),
body TEXT,
FULLTEXT ( title , body ) WITH PARSER NGRAM
) ENGINE=INNODB CHARACTER SET UTF8MB4;
Code language: SQL (Structured Query Language) (sql)
其次,使用SET NAMES
语句将字符集设置为utf8mb4
。
SET NAMES utf8mb4;
Code language: SQL (Structured Query Language) (sql)
第三,在posts
表中插入一个新行:
INSERT INTO posts(title,body)
VALUES('MySQL全文搜索','MySQL提供了具有许多好的功能的内置全文搜索'),
('MySQL教程','学习MySQL快速,简单和有趣');
Code language: SQL (Structured Query Language) (sql)
第四,要查看 ngram 如何标记文本,请使用以下语句:
SET GLOBAL innodb_ft_aux_table="test/posts";
SELECT
*
FROM
information_schema.innodb_ft_index_cache
ORDER BY
doc_id ,
position;
Code language: SQL (Structured Query Language) (sql)
此查询对于故障排除很有用。例如,如果某个单词不包含在搜索结果中,则该单词可能不会被索引,因为它是停用词或者可能是其他原因。
设置 ngram 标记大小
正如您在前面的示例中看到的,ngram 中的标记大小 (n) 默认为 2。要更改标记大小,您可以使用ngram_token_size
配置选项,该选项的值在 1 到 10 之间。
请注意,较小的标记大小会使全文搜索索引更小,并允许您更快地搜索。
由于ngram_token_size
是一个只读变量,因此您只能使用两个选项设置其值:
首先,在启动字符串中:
mysqld --ngram_token_size=1
Code language: SQL (Structured Query Language) (sql)
二、在配置文件中:
[mysqld]
ngram_token_size=1
Code language: SQL (Structured Query Language) (sql)
ngram 解析器短语搜索
MySQL 将短语搜索转换为 ngram 短语搜索。例如, "abc"
转换为"ab bc"
,这会返回包含"ab bc"
和"abc"
的文档。
以下示例显示您在posts
表中搜索短语搜索
:
SELECT
id, title, body
FROM
posts
WHERE
MATCH (title , body) AGAINST ('搜索' );
Code language: SQL (Structured Query Language) (sql)
使用 ngram 处理搜索结果
自然语言模式
在NATURAL LANGUAGE MODE
搜索中,搜索词将转换为 ngram 值的并集。假设标记大小为 2 或二元组,搜索词mysql
将转换为my
ys
sq
和ql
。
SELECT
*
FROM
posts
WHERE
MATCH (title , body)
AGAINST ('简单和有趣' IN natural language MODE);
Code language: SQL (Structured Query Language) (sql)
布尔模式
在BOOLEAN MODE
搜索中,搜索词将转换为 ngram 短语搜索。例如:
SELECT
*
FROM
posts
WHERE
MATCH (title , body)
AGAINST ('简单和有趣' IN BOOLEAN MODE);
Code language: SQL (Structured Query Language) (sql)
ngram 通配符搜索
ngram FULLTEXT
索引仅包含 ngram,因此它不知道术语的开头。当您执行通配符搜索时,可能会返回意外结果。
以下规则适用于使用 ngram FULLTEXT
搜索索引的通配符搜索:
如果通配符中的前缀术语短于 ngram 标记大小,则查询将返回包含以前缀术语开头的 ngram 标记的所有文档。例如:
SELECT
id,
title,
body
FROM
posts
WHERE
MATCH (title , body)
AGAINST ('my*' );
Code language: SQL (Structured Query Language) (sql)
如果通配符中的前缀术语比 ngram 标记大小长,MySQL 会将前缀术语转换为 ngram 短语并忽略通配符运算符。请参见以下示例:
SELECT
id,
title,
body
FROM
posts
WHERE
MATCH (title , body)
AGAINST ('mysqld*' );
Code language: SQL (Structured Query Language) (sql)
在此示例中,术语“ mysqld"
被转换为 ngram 短语: "my"
"ys"
"sq"
"ql"
"ld"
。因此,返回包含这些短语之一的所有文档。
处理停用词
ngram 解析器排除停用词列表中包含停用词的标记。例如,假设ngram_token_size
为 2 并且文档包含"abc"
。 ngram 解析器会将文档标记为"ab"
和"bc"
。如果"b"
是停用词,ngram 将排除"ab"
和"bc"
,因为它们包含"b"
。
请注意,如果语言不是英语,您必须定义自己的停用词列表。此外,长度大于ngram_token_size
的停用词将被忽略。
在本教程中,您学习了如何使用 MySQL ngram 全文解析器来处理表意语言的全文搜索。