本教學將向您展示如何使用MySQL ngram
全文解析器來支援中文,日文,韓文等表意語言的全文搜尋。
MySQL內建的全文解析器使用空格確定單詞的開始和結束。當涉及漢語,日語或韓語等表意語言語言時,這是一個限制,因為這些語言不使用分詞符。
為了解決這個問題,MySQL提供了ngram
全文解析器。自MySQL5.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'
要建立使用ngram
全文解析器的FULLTEXT
索引,可以在CREATE TABLE,ALTER TABLE或CREATE 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
中的令牌大小(n
)為2
,要更改令牌大小,請使用ngram_token_size
組態選項,值的範圍是:1
到10
。
請注意,較小的令牌大小可使較小的全文搜尋索引更快地進行搜尋。
因為ngram_token_size
是唯讀變數,因此您只能使用兩個選項設定其值:
第一種方式,在啟動字串中:
mysqld --ngram_token_size=1
第二種方式 - 在組態檔案中:
[mysqld]
ngram_token_size=1
MySQL將短語搜尋轉換成ngram
短語搜尋。 例如,abc
被轉換為ab bc
,它返回包含ab bc
和abc
的文件。
以下範例顯示在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
值的並集。 假設令牌大小為2
或者二進位制,則搜尋項mysql
被轉換為我的my
ys
sq
和ql
。
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 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_size
為2
,文件包含abc
。 ngram
解析器將文件標記為ab
和bc
。 如果b
是一個停用詞,則ngram
將包含ab
和bc
,因為它們包含b
。
請注意,如果語言不是英語,則必須定義自己的詞條列表。 此外,長度大於ngram_token_size
的停止詞將被忽略。
在本教學中,您已經學會了如何使用MySQL ngram
全文解析器來處理表意語言的全文搜尋。