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