- 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: