MySQL ngram全文本解析器
在本文中,我们将学习使用MySQL的ngram全文本解析器, 支持对表意性语言进行全文本搜索 ,例如日语、中文和韩语。
MySQL内置的全文本解析器使用 分隔符作为空格 来确定单词的开始和结束。然而,在处理日语、中文和韩语等表意性语言时,全文本解析器存在一定的 限制 ,因为它们不使用单词分隔符。
MySQL 提供了ngram全文本解析器来解决这个问题。在MySQL 5版本之后 ,MySQL将ngram全文本解析器作为一个内置的服务器插件提供。与其他内置插件类似,MySQL在启动数据库服务器时会自动加载此插件。ngram全文本解析器在MySQL的InnoDB和MyISAM存储引擎中都得到支持。
根据MySQL的定义,ngram是从给定文本序列中连续的一系列字符。它的主要功能是将文本序列标记为连续的n个字符的序列。 例如,使用ngram全文本解析器,我们可以对字符串” **java “进行不同值的 N 进行标记,结果如下所示:
N = 1: 'j', 'a', 'v', 'a'
N = 2: 'ja', 'av', 'va'
N = 3: 'jav', 'ava'
N = 4: 'java'
使用ngram解析器创建FULLTEXT索引
我们可以通过在 CREATE TABLE 、 ALTER TABLE 或 CREATE INDEX 语句中指定 WITH PARSER ngram 来创建一个带有ngram解析器的FULLTEXT索引。
考虑以下示例,它创建了一个名为” articles “的表,并添加了带有ngram全文解析器的 title 和 body 列。
mysql> CREATE TABLE articles (
id INT AUTO_INCREMENT PRIMARY KEY,
title VARCHAR(150),
body TEXT,
FULLTEXT (title, body) WITH PARSER ngram
) ENGINE=INNODB CHARACTER SET UTF8MB4;
接下来,我们将使用 SET NAMES 语句将字符集设置为 UTF8MB4 ,如下所示:
mysql> SET NAMES UTF8MB4;
接下来,将示例数据(简体中文文本)插入到表格中,如下所示:
mysql> INSERT INTO articles (title, body) VALUES
('?????', '??????????????????'),
('???????', '???????????');
第四,我们将使用以下语句来查看ngram如何对数据进行分词:
mysql> SET GLOBAL innodb_ft_aux_table = "employeedb/articles";
mysql> SELECT * FROM
INFORMATION_SCHEMA.INNODB_FT_INDEX_CACHE
ORDER BY doc_id, position;
我们将得到以下结果:
这种类型的语句有助于故障排除。 例如 ,如果我们搜索的词没有包含在其中,则该词将被视为停用词,可能不会被索引,或者可能是其他原因。
设置ngram Token大小
在前面的例子中,我们可以看到,默认情况下,ngram中的标记大小(n)为2。如果我们想要更改默认的标记大小,我们需要使用 ngram_token_size 配置选项,其值的范围为1到10。需要注意的是,较小的标记大小会导致较小的全文搜索索引,并且提供快速搜索。
ngram_token_size是只读变量,因此我们只能使用以下两个选项来设置它的值:
1. 在启动字符串中:
mysqld --ngram_token_size=1
2. 在配置文件中:
[mysqld]
ngram_token_size=1
ngram解析器中的空格处理
解析时,ngram解析器会消除空格。例如:
- “ab cd”被解析为”ab”, “cd”
- “a bc”被解析为”bc”
ngram解析器短语搜索
MySQL将短语搜索转换为ngram短语搜索。例如,我们有一个短语搜索”abc”,它被转换为”ab bc”,返回包含”abc”和”ab bc”的结果。
如果我们有一个搜索短语”abc def”,它被转换为”ab bc de ef”,它返回包含”abc def”和”ab bc de ef”的结果。它不会返回包含”abcdef”的文档。
下面的语句显示了在文章表中搜索短语??的结果:
SELECT id, title, body
FROM articles
WHERE MATCH (title, body) AGAINST ('??');
这是结果:
处理使用ngram的不同搜索模式
在这里,我们将使用以下模式来处理搜索结果:
自然语言模式
自然语言搜索模式将搜索词转换为ngram值的并集。 例如 ,如果令牌大小为2,搜索词“mysql”可以转换为my、ys、sq和ql。请参见下面的语句:
mysql> SELECT * FROM articles
WHERE MATCH (title, body)
AGAINST ('?????' IN NATURAL LANGUAGE MODE);
我们将获得所期望的结果:
布尔模式
布尔搜索模式将搜索词转换为ngram短语搜索。请参见以下语句:
mysql> SELECT * FROM articles
WHERE MATCH (title, body)
AGAINST ('?????' IN BOOLEAN MODE);
我们将获得期望的结果:
ngram解析器通配符搜索
当我们在ngram解析器中使用通配符字符进行搜索时,可能会返回意外的结果。因为ngram FULLTEXT索引仅包含ngrams,所以它不知道术语的开头。
使用ngram全文索引进行带通配符的搜索时,使用以下规则:
1. 如果ngram令牌大小大于通配符中的前缀术语,则查询将返回包含以前缀术语开头的ngram令牌的所有文档。例如:
mysql> SELECT * FROM articles
WHERE MATCH (title, body) AGAINST ('my*');
我们将获得以下结果:
2. 如果ngram标记大小小于通配符中的前缀术语,则MySQL将把前缀术语转换为ngram短语,并忽略通配符操作符。例如
mysql> SELECT * FROM articles
WHERE MATCH (title, body) AGAINST ('mysql');
在将术语”mysql”转换为Ngram短语时,我们将获得以下结果:”my” “ys” “sq” “ql”。
处理ngram解析器中的停用词
ngram解析器比较停用词列表中的单词。如果它们相等,则将该单词从索引中排除。
ngram解析器以不同的方式处理停用词。它排除包含停用词的标记,而不是排除与停用词列表相等的标记。
例如,如果ngram_token_size为2,文档包含”a,b”,那么ngram解析器将它们标记为”a,”和”,b”。如果逗号(”,”)是一个停用词,则”a,”和”,b”都会被排除,因为它们包含逗号。
需要注意的是,ngram解析器使用英文的默认停用词列表。如果我们想使用其他语言,我们必须创建自己的停用词列表。