MySQL ngram Full-Text Parser

摘要:在本教程中,您将学习如何使用 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 TABLEALTER TABLECREATE INDEX语句中添加WITH PARSER ngram

考虑以下示例。

首先,创建新的posts表,并将titlebody列添加到使用 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)
MySQL ngram full-text parser example

此查询对于故障排除很有用。例如,如果某个单词不包含在搜索结果中,则该单词可能不会被索引,因为它是停用词或者可能是其他原因。

设置 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)
MySQL ngram full-text parser phrase search

使用 ngram 处理搜索结果

自然语言模式

NATURAL LANGUAGE MODE搜索中,搜索词将转换为 ngram 值的并集。假设标记大小为 2 或二元组,搜索词mysql将转换为my ys sqql

SELECT 
    *
FROM
    posts
WHERE
    MATCH (title , body)  
    AGAINST ('简单和有趣' IN natural language MODE);
Code language: SQL (Structured Query Language) (sql)
Natural language mode

布尔模式

BOOLEAN MODE搜索中,搜索词将转换为 ngram 短语搜索。例如:

SELECT 
    *
FROM
    posts
WHERE
    MATCH (title , body) 
    AGAINST ('简单和有趣' IN BOOLEAN MODE);
Code language: SQL (Structured Query Language) (sql)

BOOLEAN MODE

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 wildcard search

如果通配符中的前缀术语比 ngram 标记大小长,MySQL 会将前缀术语转换为 ngram 短语并忽略通配符运算符。请参见以下示例:

SELECT 
    id, 
    title, 
    body
FROM
    posts
WHERE
    MATCH (title , body) 
    AGAINST ('mysqld*' );
Code language: SQL (Structured Query Language) (sql)
ngram wildcard search

在此示例中,术语“ 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 全文解析器来处理表意语言的全文搜索。

本教程有帮助吗?