MySQL - N-gram 全文解析器
MySQL - ngram 全文解析器 (用于 CJK 语言)
Section titled “MySQL - ngram 全文解析器 (用于 CJK 语言)”MySQL 中的标准全文搜索 (full-text search) 依赖于空格和标点符号等分隔符来分隔单词(分词/tokens)。这对于英语等语言效果很好,但对于汉字表意语言(如中文、日语和韩语 (CJK))则无效,这些语言通常不使用空格分隔单词。为了在这些语言中实现有效的搜索,MySQL 提供了 ngram 全文解析器 (full-text parser)。
什么是 ngram?
Section titled “什么是 ngram?”ngram 是文本字符串中连续的“n”个字符序列。ngram 解析器 (parser) 通过在文本上滑动“n”个字符的窗口来对文本进行分词 (tokenize)。“n”的值是可配置的。
例如,使用不同的“n”值对日语单词“東京” (Tokyo) 进行分词:
n=1: '東', '京' (一元模型)n=2: '東京' (二元模型)对中文短语“搜索引擎”进行分词:
n=2 (二元模型): '搜索', '索引', '引擎'配置 ngram 分词大小
Section titled “配置 ngram 分词大小”分词大小由 ngram_token_size 服务器变量控制。默认值为 2(二元模型),可设置为 1 到 10。较小的分词大小会导致索引更小,搜索更快,但可能会产生较少的相关结果。此变量在运行时是只读的,必须在您的 MySQL 配置文件 (my.cnf 或 my.ini) 中设置。
[mysqld]ngram_token_size=2您必须重启 MySQL 服务器才能使此更改生效。更改 ngram_token_size 后,您必须重建所有使用 ngram 解析器的 FULLTEXT 索引。
使用 ngram 解析器创建 FULLTEXT 索引
Section titled “使用 ngram 解析器创建 FULLTEXT 索引”要使用此解析器,您在创建 FULLTEXT 索引时需要指定 WITH PARSER ngram。至关重要的是,您的表和列应使用像 utf8mb4 这样的 Unicode 字符集。
CREATE TABLE articles ( id INT AUTO_INCREMENT PRIMARY KEY, title VARCHAR(255) NOT NULL, content TEXT NOT NULL, FULLTEXT (title, content) WITH PARSER ngram) ENGINE=InnoDB CHARACTER SET=utf8mb4;让我们插入一些日语示例文章。
INSERT INTO articles (title, content) VALUES('日本の首都', '日本の首都は東京です。'),('京都の観光', '京都には多くの有名な寺院があります。');ngram 搜索的工作原理
Section titled “ngram 搜索的工作原理”当您执行搜索时,搜索查询本身也会被分词为 ngram。
自然语言模式搜索
Section titled “自然语言模式搜索”搜索“東京”(在 ngram_token_size=2 的情况下)会变成搜索分词 '東京'。这将匹配第一篇文章。
SELECT * FROM articlesWHERE MATCH(title, content) AGAINST('東京' IN NATURAL LANGUAGE MODE);布尔模式搜索
Section titled “布尔模式搜索”布尔模式 (Boolean mode) 提供更多控制。对短语的搜索会转换为对 ngram 序列的搜索。例如,搜索 "京都 寺院"(京都 寺庙)会变为搜索包含 ngram '京都'、'都 '、' 寺'、'寺院' 且彼此邻近的文档。
SELECT * FROM articlesWHERE MATCH(title, content) AGAINST('"京都の寺院"' IN BOOLEAN MODE);这很可能匹配第二篇文章,因为它包含该字符序列。
- 空格处理:
ngram解析器将空格视为分隔符。它会移除空格,并且不会生成跨越空格的ngram。例如,"ab cd"会被解析为"ab"和"cd"的ngram,分别处理。 - 停用词处理: 常见词(停用词/stopwords)在分词前会被移除。如果一个分词在停用词列表中,它将不被索引。如果您定义了相关的停用词列表,这也适用于 CJK 语言。
- 通配符搜索: 通配符搜索 (
*) 可能不太直观。如果前缀短于ngram_token_size,它可能会返回大量结果。如果前缀更长,通配符运算符通常会被忽略,并将该术语转换为ngram短语搜索。
在客户端程序中使用 ngram 解析器 (Node.js 示例)
Section titled “在客户端程序中使用 ngram 解析器 (Node.js 示例)”以下是您如何在 Node.js 应用程序中使用 mysql2 实现搜索功能。
// searchService.jsconst pool = require('./db'); // 假设已配置 mysql2 Promise 连接池
async function searchArticles(query) { // 使用 BOOLEAN MODE 进行更精确的短语搜索。 // 添加通配符以允许末尾的部分匹配。 const searchQuery = `"${query}*"`;
const sql = ` SELECT id, title, content FROM articles WHERE MATCH(title, content) AGAINST(? IN BOOLEAN MODE);`;
try { const [rows] = await pool.execute(sql, [searchQuery]); console.log(`Found ${rows.length} results for '${query}':`); console.log(rows); return rows; } catch (error) { console.error('Full-text search failed:', error); throw error; }}
// 示例用法:// searchArticles('東京');// searchArticles('京都 観光');