
- 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
Learn MySQL in-depth with real-world projects through our MySQL certification course. Enroll and become a certified expert to boost your career.
使用 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://127.0.0.1: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: