MySQL ngram全文解析器

2019-10-16 22:55:37

本教學將向您展示如何使用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全文解析器來處理表意語言的全文搜尋。