
- MySQL 基礎
- MySQL - 首頁
- MySQL - 簡介
- MySQL - 特性
- MySQL - 版本
- MySQL - 變數
- MySQL - 安裝
- MySQL - 管理
- MySQL - PHP 語法
- MySQL - Node.js 語法
- MySQL - Java 語法
- MySQL - Python 語法
- MySQL - 連線
- MySQL - Workbench
- MySQL 資料庫
- MySQL - 建立資料庫
- MySQL - 刪除資料庫
- MySQL - 選擇資料庫
- MySQL - 顯示資料庫
- MySQL - 複製資料庫
- MySQL - 資料庫匯出
- MySQL - 資料庫匯入
- MySQL - 資料庫資訊
- MySQL 使用者
- MySQL - 建立使用者
- MySQL - 刪除使用者
- MySQL - 顯示使用者
- MySQL - 修改密碼
- MySQL - 授予許可權
- MySQL - 顯示許可權
- MySQL - 收回許可權
- MySQL - 鎖定使用者賬戶
- MySQL - 解鎖使用者賬戶
- MySQL 表
- MySQL - 建立表
- MySQL - 顯示錶
- MySQL - 修改表
- MySQL - 重命名錶
- MySQL - 克隆表
- MySQL - 截斷表
- MySQL - 臨時表
- MySQL - 修復表
- MySQL - 描述表
- MySQL - 新增/刪除列
- MySQL - 顯示列
- MySQL - 重新命名列
- MySQL - 表鎖定
- MySQL - 刪除表
- MySQL - 派生表
- MySQL 查詢
- MySQL - 查詢
- MySQL - 約束
- MySQL - 插入查詢
- MySQL - 選擇查詢
- MySQL - 更新查詢
- MySQL - 刪除查詢
- MySQL - 替換查詢
- MySQL - 插入忽略
- MySQL - 插入重複鍵更新
- MySQL - 插入到選擇
- MySQL 運算子和子句
- MySQL - WHERE 子句
- MySQL - LIMIT 子句
- MySQL - DISTINCT 子句
- MySQL - ORDER BY 子句
- MySQL - GROUP BY 子句
- MySQL - HAVING 子句
- MySQL - AND 運算子
- MySQL - OR 運算子
- MySQL - LIKE 運算子
- MySQL - IN 運算子
- MySQL - ANY 運算子
- MySQL - EXISTS 運算子
- MySQL - NOT 運算子
- MySQL - 不等於運算子
- MySQL - IS NULL 運算子
- MySQL - IS NOT NULL 運算子
- MySQL - BETWEEN 運算子
- MySQL - UNION 運算子
- MySQL - UNION 與 UNION ALL
- MySQL - MINUS 運算子
- MySQL - INTERSECT 運算子
- MySQL - INTERVAL 運算子
- MySQL 連線
- MySQL - 使用連線
- MySQL - INNER JOIN
- MySQL - LEFT JOIN
- MySQL - RIGHT JOIN
- MySQL - CROSS JOIN
- MySQL - FULL JOIN
- MySQL - 自連線
- MySQL - 刪除連線
- MySQL - 更新連線
- MySQL - UNION 與 JOIN
- MySQL 觸發器
- MySQL - 觸發器
- MySQL - 建立觸發器
- MySQL - 顯示觸發器
- MySQL - 刪除觸發器
- MySQL - INSERT 之前觸發器
- MySQL - INSERT 之後觸發器
- MySQL - UPDATE 之前觸發器
- MySQL - UPDATE 之後觸發器
- MySQL - DELETE 之前觸發器
- MySQL - DELETE 之後觸發器
- MySQL 資料型別
- MySQL - 資料型別
- MySQL - VARCHAR
- MySQL - BOOLEAN
- MySQL - ENUM
- MySQL - DECIMAL
- MySQL - INT
- MySQL - FLOAT
- MySQL - BIT
- MySQL - TINYINT
- MySQL - BLOB
- MySQL - SET
- MySQL 正則表示式
- MySQL - 正則表示式
- MySQL - RLIKE 運算子
- MySQL - NOT LIKE 運算子
- MySQL - NOT REGEXP 運算子
- MySQL - regexp_instr() 函式
- MySQL - regexp_like() 函式
- MySQL - regexp_replace() 函式
- MySQL - regexp_substr() 函式
- MySQL 函式與運算子
- MySQL - 日期和時間函式
- MySQL - 算術運算子
- MySQL - 數值函式
- MySQL - 字串函式
- MySQL - 聚合函式
- MySQL 雜項概念
- MySQL - NULL 值
- MySQL - 事務
- MySQL - 使用序列
- MySQL - 處理重複項
- MySQL - SQL 注入
- MySQL - 子查詢
- MySQL - 註釋
- MySQL - 檢查約束
- MySQL - 儲存引擎
- MySQL - 將表匯出到 CSV 檔案
- MySQL - 將 CSV 檔案匯入到資料庫
- MySQL - UUID
- MySQL - 公共表表達式
- MySQL - ON DELETE CASCADE
- MySQL - Upsert
- MySQL - 水平分割槽
- MySQL - 垂直分割槽
- MySQL - 遊標
- MySQL - 儲存函式
- MySQL - 訊號
- MySQL - 重新發送訊號
- MySQL - 字元集
- MySQL - 校對
- MySQL - 萬用字元
- MySQL - 別名
- MySQL - ROLLUP
- MySQL - 當天日期
- MySQL - 字面量
- MySQL - 儲存過程
- MySQL - EXPLAIN
- MySQL - JSON
- MySQL - 標準差
- MySQL - 查詢重複記錄
- MySQL - 刪除重複記錄
- MySQL - 選擇隨機記錄
- MySQL - SHOW PROCESSLIST
- MySQL - 更改列型別
- MySQL - 重置自動遞增
- MySQL - Coalesce() 函式
- MySQL 有用資源
- MySQL - 有用函式
- MySQL - 語句參考
- MySQL - 快速指南
- MySQL - 有用資源
- MySQL - 討論
MySQL - ngram 全文解析器
通常在全文搜尋中,內建的 MySQL 全文解析器將單詞之間的空格視為分隔符。這決定了單詞的實際開始和結束位置,使搜尋更簡單。但是,這僅適用於使用空格分隔單詞的語言。
幾種表意文字語言,如中文、日語和韓語,不使用單詞分隔符。為了支援這些語言的全文搜尋,使用了 ngram 解析器。此解析器由 InnoDB 和 MyISAM 儲存引擎都支援。
ngram 全文解析器
ngram 是從給定文字序列中連續的“n”個字元。ngram 解析器將文字序列劃分為標記,作為 n 個字元的連續序列。
例如,考慮文字“Tutorial”並觀察 ngram 解析器如何對其進行標記化:
n=1: 'T', 'u', 't', 'o', 'r', 'i', 'a', 'l' n=2: 'Tu', 'ut', 'to' 'or', 'ri', 'ia' 'al' n=3: 'Tut', 'uto', 'tor', 'ori', 'ria', 'ial' n=4: 'Tuto', 'utor', 'tori', 'oria', 'rial' n=5: 'Tutor', 'utori', 'toria', 'orial' n=6: 'Tutori', 'utoria', 'torial' n=7: 'Tutoria', 'utorial' n=8: 'Tutorial'
ngram 全文解析器是一個內建的伺服器外掛。與其他內建伺服器外掛一樣,它在伺服器啟動時自動載入。
配置 ngram 令牌大小
要更改標記大小(從其預設大小 2 開始),請使用 ngram_token_size 配置選項。ngram 值的範圍是 1 到 10。但為了提高搜尋查詢的速度,請使用較小的標記大小;因為較小的標記大小允許使用較小的全文搜尋索引進行更快的搜尋。
因為 ngram_token_size 是一個只讀變數,所以您只能使用兩種選項來設定它的值
在啟動字串中設定 --ngram_token_size
mysqld --ngram_token_size=1
在配置檔案“my.cnf”中設定 ngram_token_size
[mysqld] ngram_token_size=1
使用 ngram 解析器建立 FULLTEXT 索引
可以使用 FULLTEXT 關鍵字在表的列上建立 FULLTEXT 索引。這與 CREATE TABLE、ALTER TABLE 或 CREATE INDEX SQL 語句一起使用;您只需指定“WITH PARSER ngram”。以下是語法:
CREATE TABLE table_name ( column_name1 datatype, column_name2 datatype, column_name3 datatype, ... FULLTEXT (column_name(s)) WITH PARSER NGRAM ) ENGINE=INNODB CHARACTER SET UTF8mb4;
示例
在此示例中,我們使用 CREATE TABLE 語句建立 FULLTEXT 索引,如下所示:
CREATE TABLE blog ( ID INT AUTO_INCREMENT NOT NULL, TITLE VARCHAR(255), DESCRIPTION TEXT, FULLTEXT ( TITLE, DESCRIPTION ) WITH PARSER NGRAM, PRIMARY KEY(id) ) ENGINE=INNODB CHARACTER SET UTF8MB4; SET NAMES UTF8MB4;
現在,將資料(以任何表意文字語言)插入到建立的此表中:
INSERT INTO BLOG VALUES (NULL, '教程', '教程是對一個概念的冗長研究'), (NULL, '文章', '文章是關於一個概念的基於事實的小資訊');
要檢查文字是如何標記化的,請執行以下語句:
SET GLOBAL innodb_ft_aux_table = "customers/blog"; SELECT * FROM INFORMATION_SCHEMA.INNODB_FT_INDEX_CACHE ORDER BY doc_id, position;
ngram 解析器空格處理
ngram 解析器在解析時會消除任何空格字元。例如,考慮以下帶有標記大小 2 的 TEXT:
“ab cd”解析為“ab”、“cd”
“a bc”解析為“bc”
ngram 解析器停用詞處理
除了空格字元之外,MySQL 還具有一個停用詞列表,其中包含被視為停用詞的各種詞。如果解析器在文字中遇到停用詞列表中存在的任何單詞,則該單詞將從索引中排除。
ngram 解析器短語搜尋
普通短語搜尋將轉換為 ngram 短語搜尋。例如,搜尋短語“abc”將轉換為“ab bc”,這將返回包含“abc”和“ab bc”的文件;搜尋短語“abc def”將轉換為“ab bc de ef”,這將返回包含“abc def”和“ab bc de ef”的文件。包含“abcdef”的文件不會返回。
ngram 解析器術語搜尋
對於自然語言模式搜尋,搜尋詞將轉換為 ngram 術語的並集。例如,字串“abc”(假設 ngram_token_size=2)將轉換為“ab bc”。給定兩個文件,一個包含“ab”,另一個包含“abc”,搜尋詞“ab bc”匹配這兩個文件。
對於布林模式搜尋,搜尋詞將轉換為 ngram 短語搜尋。例如,字串“abc”(假設 ngram_token_size=2)將轉換為““ab bc””。給定兩個文件,一個包含“ab”,另一個包含“abc”,搜尋短語““ab bc””僅匹配包含“abc”的文件。
ngram 解析器萬用字元搜尋
因為 ngram FULLTEXT 索引僅包含 ngram,並且不包含有關術語開頭的資訊,所以萬用字元搜尋可能會返回意外的結果。以下行為適用於使用 ngram FULLTEXT 搜尋索引的萬用字元搜尋
如果萬用字元搜尋的字首詞短於 ngram 令牌大小,則查詢返回所有包含以該字首詞開頭的 ngram 令牌的索引行。例如,假設 ngram_token_size=2,則對 "a*" 進行搜尋將返回所有以 "a" 開頭的行。
如果萬用字元搜尋的字首詞長於 ngram 令牌大小,則將字首詞轉換為 ngram 短語,並忽略萬用字元運算子。例如,假設 ngram_token_size=2,則 "abc*" 萬用字元搜尋將轉換為 "ab bc"。
使用客戶端程式的 ngram 全文解析器
我們也可以使用客戶端程式執行 ngram 全文解析器操作。
語法
要透過 PHP 程式執行 ngram 全文解析器,我們需要使用 **mysqli** 函式 **query()** 執行 "Create" 語句,如下所示:
$sql = "CREATE TABLE blog (ID INT AUTO_INCREMENT NOT NULL, title VARCHAR(255), DESCRIPTION TEXT, FULLTEXT ( title, DESCRIPTION ) WITH PARSER NGRAM, PRIMARY KEY(id) )ENGINE=INNODB CHARACTER SET UTF8MB4"; $mysqli->query($sql);
要透過 JavaScript 程式執行 ngram 全文解析器,我們需要使用 **mysql2** 庫的 **query()** 函式執行 "Create" 語句,如下所示:
sql = `CREATE TABLE blog (ID INT AUTO_INCREMENT NOT NULL, title VARCHAR(255), DESCRIPTION TEXT, FULLTEXT ( title, DESCRIPTION ) WITH PARSER NGRAM, PRIMARY KEY(id) )ENGINE=INNODB CHARACTER SET UTF8MB4`; con.query(sql);
要透過 Java 程式執行 ngram 全文解析器,我們需要使用 **JDBC** 函式 **execute()** 執行 "Create" 語句,如下所示:
String sql = "CREATE TABLE blog (ID INT AUTO_INCREMENT NOT NULL, title VARCHAR(255), description TEXT," + " FULLTEXT ( title, description ) WITH PARSER NGRAM, PRIMARY KEY(id) )ENGINE=INNODB CHARACTER SET UTF8MB4"; statement.execute(sql);
要透過 Python 程式執行 ngram 全文解析器,我們需要使用 **MySQL Connector/Python** 的 **execute()** 函式執行 "Create" 語句,如下所示:
create_table_query = 'CREATE TABLE blog(ID INT AUTO_INCREMENT NOT NULL, title VARCHAR(255), description TEXT, FULLTEXT (title, description) WITH PARSER NGRAM, PRIMARY KEY(id)) ENGINE=INNODB CHARACTER SET UTF8MB4' cursorObj.execute(queryexpansionfulltext_search)
示例
以下是程式:
$dbhost = "localhost"; $dbuser = "root"; $dbpass = "password"; $dbname = "TUTORIALS"; $mysqli = new mysqli($dbhost, $dbuser, $dbpass, $dbname); if ($mysqli->connect_errno) { printf("Connect failed: %s
", $mysqli->connect_error); exit(); } // printf('Connected successfully.
'); /*CREATE Table*/ $sql = "CREATE TABLE blog (ID INT AUTO_INCREMENT NOT NULL, title VARCHAR(255), description TEXT, FULLTEXT ( title, description ) WITH PARSER NGRAM, PRIMARY KEY(id) )ENGINE=INNODB CHARACTER SET UTF8MB4"; $result = $mysqli->query($sql); if ($result) { printf("Table created successfully...!\n"); } //insert data $q = "INSERT INTO blog (id, title, description) VALUES (NULL, '教程', '教程是對一個概念的冗長研究'), (NULL, '文章', '文章是關於一個概念的基於事實的小資訊')"; if ($res = $mysqli->query($q)) { printf("Data inserted successfully...!\n"); } //we will use the below statement to see how the ngram tokenizes the data: $setglobal = "SET GLOBAL innodb_ft_aux_table = 'TUTORIALS/blog'"; if ($mysqli->query($setglobal)) { echo "global innodb_ft_aux_table set...!"; } $s = "SELECT * FROM INFORMATION_SCHEMA.INNODB_FT_INDEX_CACHE ORDER BY doc_id, position "; if ($r = $mysqli->query($s)) { print_r($r); } //display data (ngram parser phrase search); $query = "SELECT * FROM blog WHERE MATCH (title, description) AGAINST ('教程')"; if ($r = $mysqli->query($query)) { printf("Table Records: \n"); while ($row = $r->fetch_assoc()) { printf( "ID: %d, Title: %s, Descriptions: %s", $row["id"], $row["title"], $row["description"] ); printf("\n"); } } else { printf("Failed"); } $mysqli->close();
輸出
獲得的輸出如下所示:
global innodb_ft_aux_table set...!mysqli_result Object ( [current_field] => 0 [field_count] => 6 [lengths] => [num_rows] => 62 [type] => 0 ) Table Records: ID: 1, Title: 教程, Descriptions: 教程是對一個概念的冗長研究 ID: 3, Title: 教程, Descriptions: 教程是對一個概念的冗長研究
var mysql = require("mysql2"); var con = mysql.createConnection({ host: "localhost", user: "root", password: "password", }); //Connecting to MySQL con.connect(function (err) { if (err) throw err; // console.log("Connected successfully...!"); // console.log("--------------------------"); sql = "USE TUTORIALS"; con.query(sql); //create a table... sql = `CREATE TABLE blog (ID INT AUTO_INCREMENT NOT NULL, title VARCHAR(255), description TEXT, FULLTEXT ( title, description ) WITH PARSER NGRAM, PRIMARY KEY(id) )ENGINE=INNODB CHARACTER SET UTF8MB4`; con.query(sql); //insert data sql = `INSERT INTO blog (id, title, description) VALUES (NULL, '教程', '教程是對一個概念的冗長研究'), (NULL, '文章', '文章是關於一個概念的基於事實的小資訊')`; con.query(sql); //we will use the below statement to see how the ngram tokenizes the data: sql = "SET GLOBAL innodb_ft_aux_table = 'TUTORIALS/blog'"; con.query(sql); //display the table details; sql = `SELECT * FROM blog WHERE MATCH (title, description) AGAINST ('教程')`; con.query(sql, function (err, result) { if (err) throw err; console.log(result); }); });
輸出
獲得的輸出如下所示:
[ { id: 1, title: '教程', description: '教程是對一個概念的冗長研究' } ]
import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.Statement; public class NgRamFSearch { public static void main(String[] args) { String url = "jdbc:mysql://:3306/TUTORIALS"; String username = "root"; String password = "password"; try { Class.forName("com.mysql.cj.jdbc.Driver"); Connection connection = DriverManager.getConnection(url, username, password); Statement statement = connection.createStatement(); System.out.println("Connected successfully...!"); //creating a table that takes fulltext column with parser ngram...! String sql = "CREATE TABLE blog (id INT AUTO_INCREMENT NOT NULL, title VARCHAR(255), description TEXT," + " FULLTEXT ( title, description ) WITH PARSER NGRAM, PRIMARY KEY(id) )ENGINE=INNODB CHARACTER SET UTF8MB4"; statement.execute(sql); //System.out.println("Table created successfully...!"); //inserting data to the table String insert = "INSERT INTO blog (id, title, description) VALUES (NULL, '教程', '教程是對一個概念的冗長研究')," + " (NULL, '文章', '文章是關於一個概念的基於事實的小資訊')"; statement.execute(insert); //System.out.println("Data inserted successfully...!"); //we will use the below statement to see how the ngram tokenizes the data: String set_global = "SET GLOBAL innodb_ft_aux_table = 'TUTORIALS/blog'"; statement.execute(set_global); ResultSet resultSet = statement.executeQuery("SELECT * FROM INFORMATION_SCHEMA.INNODB_FT_INDEX_CACHE ORDER BY doc_id, position "); System.out.println("Information schema order by Id...!"); while (resultSet.next()){ System.out.println(resultSet.getString(1)+" "+resultSet.getString(2)); } //displaying the data...! String query = "SELECT * FROM blog WHERE MATCH (title, description) AGAINST ('教程')"; ResultSet resultSet1 = statement.executeQuery(query); System.out.println("table records:"); while (resultSet1.next()){ System.out.println(resultSet1.getString(1)+" "+resultSet1.getString(2)+ " "+resultSet1.getString(3)); } connection.close(); } catch (Exception e) { System.out.println(e); } } }
輸出
獲得的輸出如下所示:
Connected successfully...! Information schema order by Id...! 教程 2 教程 2 程是 2 是對 2 對一 2 一個 2 個概 2 概念 2 唸的 2 的冗 2 冗長 2 長研 2 研究 2 文章 3 文章 3 章是 3 是關 3 關於 3 於一 3 一個 2 個概 2 概念 2 唸的 2 的基 3 基於 3 於事 3 事實 3 實的 3 的小 3 小信 3 資訊 3 table records: 1 教程 教程是對一個概念的冗長研究
import mysql.connector # Establishing the connection connection = mysql.connector.connect( host='localhost', user='root', password='password', database='tut' ) # Creating a cursor object cursorObj = connection.cursor() # Create the blog table with NGRAM full-text parser create_table_query = ''' CREATE TABLE blog ( id INT AUTO_INCREMENT NOT NULL, title VARCHAR(255), description TEXT, FULLTEXT (title, description) WITH PARSER NGRAM, PRIMARY KEY(id) ) ENGINE=INNODB CHARACTER SET UTF8MB4; ''' cursorObj.execute(create_table_query) print("Table 'blog' is created successfully!") # Set the character set to UTF8MB4 set_charset_query = "SET NAMES UTF8MB4;" cursorObj.execute(set_charset_query) print("Character set is set to UTF8MB4.") # Insert data into the blog table data_to_insert = [ ('教程', '教程是對一個概念的冗長研究'), ('文章', '文章是關於一個概念的基於事實的小資訊') ] insert_query = "INSERT INTO blog (title, description) VALUES (%s, %s)" cursorObj.executemany(insert_query, data_to_insert) connection.commit() print("Data inserted into the 'blog' table.") # Query the INNODB_FT_INDEX_CACHE table to get the full-text index information query_index_cache_query = "SELECT * FROM INFORMATION_SCHEMA.INNODB_FT_INDEX_CACHE ORDER BY doc_id, position;" cursorObj.execute(query_index_cache_query) results = cursorObj.fetchall() print("Results of INNODB_FT_INDEX_CACHE table:") for row in results: print(row) # Close the cursor and connection cursorObj.close() connection.close()
輸出
獲得的輸出如下所示:
Table 'blog' is created successfully! Character set is set to UTF8MB4. Data inserted into the 'blog' table. Results of INNODB_FT_INDEX_CACHE table: