MySQL ngram全文解析器

本教程將向您展示如何使用MySQL ngram全文解析器來支持中文,日文,韓文等表意語言的全文搜索。

MySQL ngram全文解析器簡介

MySQL內置的全文解析器使用空格確定單詞的開始和結束。當涉及漢語,日語或韓語等表意語言語言時,這是一個限制,因為這些語言不使用分詞符。

為了解決這個問題,MySQL提供了ngram全文解析器。自MySQL5.7.6版起,MySQL將ngram全文解析器作為內置的伺服器插件,這意味著當MySQL資料庫伺服器啟動時,MySQL會自動加載該插件。 MySQL支持用於InnoDBMyISAM存儲引擎的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'

使用 ngram 解析器創建FULLTEXT索引

要創建使用ngram全文解析器的FULLTEXT索引,可以在CREATE TABLEALTER TABLECREATE INDEX語句中添加WITH PARSER ngram

例如,以下語句創建新的帖子表,並將標題和正文列添加到使用ngram全文解析器的FULLTEXT索引。

USE testdb;
CREATE TABLE posts (
    id INT PRIMARY KEY AUTO_INCREMENT,
    title VARCHAR(255),
    body TEXT,
    FULLTEXT ( title , body ) WITH PARSER NGRAM
)  ENGINE=INNODB CHARACTER SET UTF8;

以下INSERT語句賂posts表中插入一個新行:

SET NAMES utf8;

INSERT INTO posts(title,body)
VALUES('MySQL全文搜索','MySQL提供了具有許多好的功能的內置全文搜索'),
      ('MySQL教學','學習MySQL快速,簡單和有趣');

請注意,SET NAMES語句設置客戶端和服務器將用於發送和接收數據的字元集; 在本示例中,它使用的是utf8

要查看ngram如何標記文本,請使用以下語句:

SET GLOBAL innodb_ft_aux_table="testdb/posts";

SELECT
    *
FROM
    information_schema.innodb_ft_index_cache
ORDER BY doc_id , position;

執行上面查詢語句,得到以下結果 -

mysql> SELECT
    *
FROM
    information_schema.innodb_ft_index_cache
ORDER BY doc_id , position;
+------+--------------+-------------+-----------+--------+----------+
| WORD | FIRST_DOC_ID | LAST_DOC_ID | DOC_COUNT | DOC_ID | POSITION |
+------+--------------+-------------+-----------+--------+----------+
| my   |            2 |           3 |         2 |      2 |        0 |
| ys   |            2 |           3 |         2 |      2 |        1 |
| sq   |            2 |           3 |         2 |      2 |        2 |
| ql   |            2 |           3 |         2 |      2 |        3 |
| l全  |            2 |           2 |         1 |      2 |        4 |
| 全文 |            2 |           2 |         1 |      2 |        5 |
| 文搜 |            2 |           2 |         1 |      2 |        8 |
| 搜索 |            2 |           2 |         1 |      2 |       11 |
| ql   |            2 |           3 |         2 |      2 |       18 |
| my   |            2 |           3 |         2 |      2 |       18 |
| ys   |            2 |           3 |         2 |      2 |       18 |
| sq   |            2 |           3 |         2 |      2 |       18 |
| l提  |            2 |           2 |         1 |      2 |       22 |
| 提供 |            2 |           2 |         1 |      2 |       23 |
| 供了 |            2 |           2 |         1 |      2 |       26 |
| 了具 |            2 |           2 |         1 |      2 |       29 |
| 具有 |            2 |           2 |         1 |      2 |       32 |
| 有許 |            2 |           2 |         1 |      2 |       35 |
| 許多 |            2 |           2 |         1 |      2 |       38 |
| 多好 |            2 |           2 |         1 |      2 |       41 |
| 好的 |            2 |           2 |         1 |      2 |       44 |
| 的功 |            2 |           2 |         1 |      2 |       47 |
| 功能 |            2 |           2 |         1 |      2 |       50 |
| 能的 |            2 |           2 |         1 |      2 |       53 |
| 的內 |            2 |           2 |         1 |      2 |       56 |
| 內置 |            2 |           2 |         1 |      2 |       59 |
| 搜索 |            2 |           2 |         1 |      2 |       60 |
| 文搜 |            2 |           2 |         1 |      2 |       60 |
| 全文 |            2 |           2 |         1 |      2 |       60 |
| 置全 |            2 |           2 |         1 |      2 |       62 |
| my   |            2 |           3 |         2 |      3 |        0 |
| ys   |            2 |           3 |         2 |      3 |        1 |
| sq   |            2 |           3 |         2 |      3 |        2 |
| ql   |            2 |           3 |         2 |      3 |        3 |
| l教  |            3 |           3 |         1 |      3 |        4 |
| 教學 |            3 |           3 |         1 |      3 |        5 |
| 學習 |            3 |           3 |         1 |      3 |       12 |
| 習m  |            3 |           3 |         1 |      3 |       15 |
| sq   |            2 |           3 |         2 |      3 |       18 |
| ql   |            2 |           3 |         2 |      3 |       18 |
| my   |            2 |           3 |         2 |      3 |       18 |
| ys   |            2 |           3 |         2 |      3 |       18 |
| l快  |            3 |           3 |         1 |      3 |       22 |
| 快速 |            3 |           3 |         1 |      3 |       23 |
| 速, |            3 |           3 |         1 |      3 |       26 |
| ,簡 |            3 |           3 |         1 |      3 |       29 |
| 簡單 |            3 |           3 |         1 |      3 |       32 |
| 單和 |            3 |           3 |         1 |      3 |       35 |
| 和有 |            3 |           3 |         1 |      3 |       38 |
| 有趣 |            3 |           3 |         1 |      3 |       41 |
+------+--------------+-------------+-----------+--------+----------+
50 rows in set

此查詢對於故障排除目的很有用。例如,如果一個單詞不包括在搜索結果中,則該單詞可能沒有被編入索引,因為它是一個停止詞或者可能是其他原因。

設置ngram令牌大小

在前面的示例可以看到,默認情況下,ngram中的令牌大小(n)為2,要更改令牌大小,請使用ngram_token_size配置選項,值的範圍是:110

請注意,較小的令牌大小可使較小的全文搜索索引更快地進行搜索。

因為ngram_token_size是只讀變數,因此您只能使用兩個選項設置其值:

第一種方式,在啟動字串中:

mysqld --ngram_token_size=1

第二種方式 - 在配置檔中:

[mysqld]
ngram_token_size=1

ngram解析器短語搜索

MySQL將短語搜索轉換成ngram短語搜索。 例如,abc被轉換為ab bc,它返回包含ab bcabc的文檔。

以下示例顯示在posts表中搜索短語:搜索

SELECT
    id, title, body
FROM
    posts
WHERE
    MATCH (title , body) AGAINST ('搜索' );

執行上面查詢語句,得到以下結果 -

mysql> SELECT
    id, title, body
FROM
    posts
WHERE
    MATCH (title , body) AGAINST ('搜索' );
+----+---------------+-------------------------------------------+
| id | title         | body                                      |
+----+---------------+-------------------------------------------+
|  1 | MySQL全文搜索 | MySQL提供了具有許多好的功能的內置全文搜索 |
+----+---------------+-------------------------------------------+
1 row in set

用ngram處理搜索結果

自然語言模式

在自然語言模式搜索中,搜索項被轉換為ngram值的並集。 假設令牌大小為2或者二進位,則搜索項mysql被轉換為我的my ys sqql

SELECT
    *
FROM
    posts
WHERE
    MATCH (title , body) AGAINST ('簡單和有趣' IN natural language MODE);

執行上面查詢語句,得到以下結果 -

mysql> SELECT
    *
FROM
    posts
WHERE
    MATCH (title , body) AGAINST ('簡單和有趣' IN natural language MODE);
+----+-----------+---------------------------+
| id | title     | body                      |
+----+-----------+---------------------------+
|  2 | MySQL教學 | 學習MySQL快速,簡單和有趣 |
+----+-----------+---------------------------+
1 row in set

布爾模式

BOOLEAN MODE搜索中,搜索項被轉換成ngram短語搜索。 例如:

SELECT
    *
FROM
    posts
WHERE
    MATCH (title , body) AGAINST ('簡單和有趣' IN BOOLEAN MODE);

執行上面查詢語句,得到以下結果 -

mysql> SELECT
    *
FROM
    posts
WHERE
    MATCH (title , body) AGAINST ('簡單和有趣' IN BOOLEAN MODE);
+----+-----------+---------------------------+
| id | title     | body                      |
+----+-----------+---------------------------+
|  2 | MySQL教學 | 學習MySQL快速,簡單和有趣 |
+----+-----------+---------------------------+
1 row in set

ngram通配符搜索

ngram FULLTEXT索引僅包含ngram,因此它不知道短語的開始。執行通配符搜索時,可能會返回意外的結果。

以下規則將應用於使用ngram FULLTEXT搜索索引的通配符搜索:

如果通配符中的首碼短語短於ngram令牌大小,則查詢返回所有包含以前綴項為起始的ngram令牌的文檔。 例如:

SELECT
    id, title, body
FROM
    posts
WHERE
    MATCH (title , body) AGAINST ('my*' );

執行上面查詢語句,得到以下結果 -

mysql> SELECT
    id, title, body
FROM
    posts
WHERE
    MATCH (title , body) AGAINST ('my*' );
+----+---------------+-------------------------------------------+
| id | title         | body                                      |
+----+---------------+-------------------------------------------+
|  1 | MySQL全文搜索 | MySQL提供了具有許多好的功能的內置全文搜索 |
|  2 | MySQL教學     | 學習MySQL快速,簡單和有趣                 |
+----+---------------+-------------------------------------------+
2 rows in set

如果通配符中的首碼短語長於ngram令牌大小,則MySQL將將首碼術語轉換為ngram短語,並忽略通配符運算符。 請參閱以下示例:

SELECT
    id, title, body
FROM
    posts
WHERE
    MATCH (title , body) AGAINST ('mysqld*' );

執行上面查詢語句,得到以下結果 -

mysql> SELECT
    id, title, body
FROM
    posts
WHERE
    MATCH (title , body) AGAINST ('mysqld*' );
+----+---------------+-------------------------------------------+
| id | title         | body                                      |
+----+---------------+-------------------------------------------+
|  1 | MySQL全文搜索 | MySQL提供了具有許多好的功能的內置全文搜索 |
|  2 | MySQL教學     | 學習MySQL快速,簡單和有趣                 |
+----+---------------+-------------------------------------------+
2 rows in set

在這個例子中,短語“mysqld”被轉換為ngram短語:my ys sq ql ld,因此返回包含其中一個短語的所有文檔。

處理停止詞

ngram解析器不包括在停止詞列表中包含停止詞的令牌。例如,假設ngram_token_size2,文檔包含abcngram解析器將文檔標記為abbc。 如果b是一個停用詞,則ngram將包含abbc,因為它們包含b

請注意,如果語言不是英語,則必須定義自己的詞條列表。 此外,長度大於ngram_token_size的停止詞將被忽略。

在本教學中,您已經學會了如何使用MySQL ngram全文解析器來處理表意語言的全文搜索。


上一篇: MySQL全文搜索 下一篇: MySQL函數