内置的 MySQL 全文解析器使用单词之间的空格作为分隔符来确定单词的开始和结束位置,这对于不使用单词分隔符的表意语言时是一个限制。为了解决这个限制,MySQL 提供了 ngram 全文解析器,支持中文、日文和韩文(CJK)。ngram 全文解析器支持与 InnoDB 和 MyISAM 一起使用。MySQL 还提供了一个用于日语的 MeCab 全文解析器插件,它将文档标记解析为有意义的单词。ngram 是由给定文本序列中的 n 个字符组成的连续序列。ngram 解析器将一个文本序列标记解析为 n 个字符的连续序列。例如,可以使用 ngram 全文解析器将 “abcd” 标记解析为不同的 n 个字符。n=1: 'a', 'b', 'c', 'd'
n=2: 'ab', 'bc', 'cd'
n=3: 'abc', 'bcd'
n=4: 'abcd'
ngram 全文解析器是一个内置的服务器插件。与其他内置服务器插件一样,它在服务器启动时自动加载。之前介绍的全文搜索语法适用于 ngram 解析器插件。本节描述解析行为的差异。除最小和最大单词长度选项(innodb_ft_min_token_size、innodb_ft_max_token_size、ft_min_word_len、ft_max_word_len)外,与全文搜索相关的配置选项也适用。ngram 解析器的默认 ngram 标记大小为 2 (bigram)。例如,当标记大小为 2 时,ngram 解析器将字符串 “abc def” 解析为四个标记:“ab”, “bc”, “de” 和 “ef”。ngram 标记大小可以使用 ngram_token_size 配置选项进行配置,该选项的最小值为 1,最大值为 10。通常,ngram_token_size 被设置为想要搜索的最大标记的大小。如果只打算搜索单个字符,那么将 ngram_token_size 设置为 1。较小的标记大小产生较小的全文搜索索引,搜索速度更快。如果需要搜索由多个字符组成的单词,请相应地设置 ngram_token_size。例如 “Happy Birthday” 在简体中文中是 “生日快乐”,“生日” 是 “birthday”,“快乐” 翻译为 “happy”。要搜索这样的双字符单词,请将 ngram_token_size 设置为 2 或更高的值。作为一个只读变量,ngram_token_size 只能作为启动字符串的一部分或在配置文件中设置:mysqld --ngram_token_size=2
[mysqld]
ngram_token_size=2
对于使用 ngram 解析器的 FULLTEXT 索引,将忽略以下最小和最大单词长度配置选项:innodb_ft_min_token_size、innodb_ft_max_token_size、ft_min_word_len 和 ft_max_word_len。创建使用 ngram 解析器的 FULLTEXT 索引要创建一个使用 ngram 解析器的 FULLTEXT 索引,请使用 CREATE TABLE、ALTER TABLE 或 CREATE INDEX 语句,并指定 WITH PARSER ngram。下面的示例演示了创建带有 ngram FULLTEXT 索引的表,插入示例数据(简体中文文本)以及在 INFORMATION_SCHEMA.INNODB_FT_INDEX_CACHE 表中查看标记化数据。mysql> USE test;
mysql> 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;
mysql> SET NAMES utf8mb4;
INSERT INTO articles (title,body) VALUES
('数据库管理','在本教程中我将向你展示如何管理数据库'),
('数据库应用开发','学习开发数据库应用程序');
mysql> SET GLOBAL innodb_ft_aux_table="test/articles";
mysql> SELECT * FROM INFORMATION_SCHEMA.INNODB_FT_INDEX_CACHE ORDER BY doc_id, position;
若要向现有表添加 FULLTEXT 索引,可以使用 ALTER TABLE 或 CREATE INDEX 语句,例如:CREATE TABLE articles (
id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,
title VARCHAR(200),
body TEXT
) ENGINE=InnoDB CHARACTER SET utf8;
ALTER TABLE articles ADD FULLTEXT INDEX ft_index (title,body) WITH PARSER ngram;
# Or:
CREATE FULLTEXT INDEX ft_index ON articles (title,body) WITH PARSER ngram;
内置的 MySQL 全文解析器将单词与终止词列表中的条目进行比较。如果一个单词等于终止词列表中的一个条目,则该单词将从索引中排除。对于 ngram 解析器,终止词处理的执行方式不同。ngram 解析器不排除与终止词列表中的条目相等的标记,而是排除包含终止词的标记。例如,假设 ngram_token_size=2,一个包含 “a,b” 的文档被解析为 “a,” 和 “,b”。如果逗号(“,”)被定义为终止词,“a,” 和 “,b” 都将从索引中排除,因为它们包含一个逗号。默认情况下,ngram 解析器使用默认终止词列表,是一个英文终止词列表。若需要适用于中文、日文或韩文的终止词列表,必须自己创建。长度大于 ngram_token_size 的终止词将被忽略。对于自然语言模式搜索,搜索词被转换为 ngram 词的合集。例如,字符串 “abc”(假设 ngram_token_size=2)被转换为 “ab bc”。给定两个文档,一个包含 “ab”,另一个包含 “abc”,搜索词 “ab bc” 匹配这两个文档。对于布尔模式搜索,搜索词被转换为 ngram 词组搜索。例如,字符串 'abc'(假设 ngram_token_size=2)被转换为 '“ab bc”'。给定两个文档,一个包含 'ab',另一个包含 'abc',搜索词组 '“ab bc”' 只匹配包含 'abc' 的文档。因为一个 ngram FULLTEXT 索引只包含 ngram,而不包含关于词语开头的信息,所以通配符搜索可能会返回意外的结果。以下行为适用于使用 ngram FULLTEXT 搜索索引的通配符搜索:● 如果通配符搜索的前缀项小于 ngram 标记的大小,则查询返回所有以前缀项开头包含 ngram 的标记的索引行。例如,假设 ngram_token_size=2,对“a*”的搜索将返回所有以 “a” 开头的行。● 如果通配符搜索的前缀项大于 ngram 标记的大小,则前缀项将被转换为 ngram 词组,通配符操作符将被忽略。例如,假设 ngram_token_size=2,“abc*” 通配符搜索将被转换为 “ab bc”。词组搜索被转换为 ngram 词组搜索。例如,搜索词组 “abc” 被转换为 “ab bc”,它返回包含 “abc” 和 “ab bc” 的文档。搜索词组 “abc def” 被转换为 “ab bc de ef”,它返回包含 “abc def” 和 “ab bc de ef” 的文档。不返回包含 “abcdef” 的文档。https://dev.mysql.com/doc/refman/8.0/en/fulltext-search-ngram.html