### 12.10.8 ngram 全文解析器

内置的 MySQL 全文解析器使用单词之间的空白作为分隔符来确定单词的开始和结束位置，这是使用不使用单词分隔符的表意语言时的限制。为了解决这个限制，MySQL 提供了一个支持中文、日文和韩文 (CJK) 的 ngram 全文解析器。支持使用 ngram 全文解析器[`InnoDB`](innodb-storage-engine.html)和[`MyISAM`](myisam-storage-engine.html).

笔记

MySQL 还为日语提供了 MeCab 全文解析器插件，它将文档标记为有意义的单词。有关详细信息，请参阅[第 12.10.9 节，“MeCab 全文解析器插件”](fulltext-search-mecab.html).

一个 ngram 是一个连续的序列*`n`*给定文本序列中的字符。ngram 解析器将一个文本序列标记为一个连续的序列*`n`*人物。例如，您可以将“abcd”标记为不同的值*`n`*使用 ngram 全文解析器。

```
n=1: 'a', 'b', 'c', 'd'
n=2: 'ab', 'bc', 'cd'
n=3: 'abc', 'bcd'
n=4: 'abcd'
```

ngram 全文解析器是一个内置的服务器插件。与其他内置服务器插件一样，它会在服务器启动时自动加载。

全文搜索语法[第 12.10 节，“全文搜索功能”](fulltext-search.html)适用于 ngram 解析器插件。本节描述了解析行为的差异。全文相关的配置选项，除了最小和最大字长选项（[`innodb_ft_min_token_size`](innodb-parameters.html#sysvar_innodb_ft_min_token_size),[`innodb_ft_max_token_size`](innodb-parameters.html#sysvar_innodb_ft_max_token_size),[`ft_min_word_len`](server-system-variables.html#sysvar_ft_min_word_len),[`ft_max_word_len`](server-system-variables.html#sysvar_ft_max_word_len))也适用。

#### 配置ngram令牌大小

ngram解析器的默认ngram令牌大小为2（bigram）。例如，当令牌大小为2时，ngram解析器将字符串“abc def”解析为四个令牌：“ab”、“bc”、“de”和“ef”。

ngram令牌大小可使用[`ngram_令牌_大小`](server-system-variables.html#sysvar_ngram_token_size)配置选项，最小值为1，最大值为10。

典型的[`ngram_令牌_大小`](server-system-variables.html#sysvar_ngram_token_size)设置为要搜索的最大令牌的大小。如果只想搜索单个字符，请设置[`ngram_令牌_大小`](server-system-variables.html#sysvar_ngram_token_size)1。令牌大小越小，全文搜索索引越小，搜索速度也越快。如果需要搜索由多个字符组成的单词，请设置[`ngram_令牌_大小`](server-system-variables.html#sysvar_ngram_token_size)照着例如，“生日快乐”是生日快乐” 简体中文中的where“生日” 是“生日”，和“快乐” 翻译为“快乐”。要搜索这样的两个字符的单词，请设置[`ngram_令牌_大小`](server-system-variables.html#sysvar_ngram_token_size)设置为2或更高的值。

作为只读变量，[`ngram_令牌_大小`](server-system-variables.html#sysvar_ngram_token_size)只能作为启动字符串的一部分或在配置文件中设置：

-   启动字符串：

    ```
    mysqld --ngram_token_size=2
    ```

-   配置文件：

    ```
    [mysqld]
    ngram_token_size=2
    ```

笔记

以下最小和最大字长配置选项将被忽略`全文`使用ngram解析器的索引：[`innodb_ft_min_令牌_大小`](innodb-parameters.html#sysvar_innodb_ft_min_token_size),[`innodb_ft_max_token_size`](innodb-parameters.html#sysvar_innodb_ft_max_token_size), [`ft_min_word_len`](server-system-variables.html#sysvar_ft_min_word_len)和[`ft_max_word_len`](server-system-variables.html#sysvar_ft_max_word_len).

#### 创建使用ngram解析器的全文索引

创建一个`全文`使用ngram解析器的索引，指定`使用语法分析器ngram`具有[`创建表格`](create-table.html), [`改变桌子`](alter-table.html)或[`创建索引`](create-index.html).

下面的示例演示如何使用`恩格拉姆` `全文`索引，插入样本数据（简体中文文本），并在[`信息模式。INNODB_FT_INDEX_缓存`](information-schema-innodb-ft-index-cache-table.html)桌子

```
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;
```

添加`全文`索引到现有表，可以使用[`改变桌子`](alter-table.html)或[`创建索引`](create-index.html).例如：

```
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;
```

#### ngram解析器空间处理

ngram解析器在解析时消除了空格。例如：

-   “ab cd”被解析为“ab”，“cd”

-   “一个bc”被解析为“bc”

#### ngram解析器停止字处理

内置的MySQL全文解析器将单词与停止词列表中的条目进行比较。如果一个单词等于“停止字”列表中的一个条目，则该单词将从索引中排除。对于ngram解析器，停止字处理的执行方式不同。ngram解析器不排除与stopword列表中的条目相等的令牌，而是排除*包含*停止说话。例如，假设[`ngram_令牌_大小=2`](server-system-variables.html#sysvar_ngram_token_size)，包含“a，b”的文档被解析为“a”，和“b”。如果将逗号（“，”）定义为停止字，则“a”和“b”都将从索引中排除，因为它们包含逗号。

默认情况下，ngram解析器使用默认的停止词列表，其中包含英语停止词列表。对于适用于中文、日文或韩文的停止词列表，您必须创建自己的停止词列表。有关创建停止字列表的信息，请参阅[第12.10.4节，“全文停止语”](fulltext-stopwords.html).

长度大于[`ngram_令牌_大小`](server-system-variables.html#sysvar_ngram_token_size)都被忽略了。

#### 语法分析器术语搜索

对于*自然语言模式*搜索时，搜索项被转换为ngram项的并集。例如，字符串“abc”（假设[`ngram_令牌_大小=2`](server-system-variables.html#sysvar_ngram_token_size))已转换为“ab bc”。给定两个文档，一个包含“ab”，另一个包含“abc”，搜索词“ab bc”匹配这两个文档。

对于*布尔模式搜索*，将搜索词转换为ngram短语搜索。例如，字符串“abc”（假设[`ngram_令牌_大小=2`](server-system-variables.html#sysvar_ngram_token_size))转换为“ab bc”。给定两个文档，一个包含“ab”，另一个包含“abc”，搜索短语“ab bc”只与包含“abc”的文档匹配。

#### ngram解析器通配符搜索

因为一个ngram`全文`索引只包含ngrams，不包含有关术语开头的信息，通配符搜索可能会返回意外结果。以下行为适用于使用ngram的通配符搜索`全文`搜索索引：

-   如果通配符搜索的前缀项小于ngram令牌大小，则查询将返回包含以前缀项开头的ngram令牌的所有索引行。例如，假设[`ngram_令牌_大小=2`](server-system-variables.html#sysvar_ngram_token_size)，搜索“a”\*“返回以“a”开头的所有行。

-   如果通配符搜索的前缀项长于ngram令牌大小，则前缀项将转换为ngram短语，并忽略通配符运算符。例如，假设[`ngram_令牌_大小=2`](server-system-variables.html#sysvar_ngram_token_size)“abc”\*通配符搜索被转换为“ab bc”。

#### 语法分析器短语搜索

短语搜索转换为ngram短语搜索。例如，搜索短语“abc”被转换为“ab bc”，它返回包含“abc”和“ab bc”的文档。

搜索短语“abc def”转换为“ab bc de ef”，返回包含“abc def”和“ab bc de ef”的文档。不返回包含“abcdef”的文档。
