MySQL 全文检索的使用示例


Posted in MySQL onJune 07, 2021

1. 环境准备

MySQL 5.7.6之前,全文索引只支持英文全文索引,不支持中文全文索引,需要利用分词器把中文段落预处理拆分成单词,然后存入数据库。 MySQL 5.7.6开始,MySQL内置了ngram全文解析器,用来支持中文、日文、韩文分词。 本文使用的MySQL 版本是5.7.22,InnoDB数据库引擎。

所以这里需要MySQL的版本大于5.7.6

-- 查看mysql的版本
mysql> select version();
+-----------+
| version() |
+-----------+
| 5.7.33    |
+-----------+
1 row in set (0.02 sec)

在 mysql 配置文件中添加分词以及最小词语长度 (如果已经配置可以忽略)

ft_min_word_len 最小字符长度默认为 4,在英文条件下确实比较合理中文情况下需要修改;

ngram_token_size 分词的最小长度 举个例子 不同长度对 你好世界 的分词

n=1: '你', '好', '世', '界' 
n=2: '你好', '好世', '世界' 
n=3: '你好世', '好世界' 
n=4: '你好世界'
# /etc/mysql/mysql.conf.d/mysqld.cnf

ft_min_word_len = 2
ngram_token_size = 2


# 如果没有则新增配置
echo 'ft_min_word_len = 2
ngram_token_size = 2' >> mysqld.cnf

# 重启服务
/etc/init.d/mysql restart
-- 查看配置
mysql> 
SHOW VARIABLES LIKE 'ft_min_word_len';
SHOW VARIABLES LIKE 'ngram_token_size';
+-----------------+-------+
| Variable_name   | Value |
+-----------------+-------+
| ft_min_word_len | 2     |
+-----------------+-------+
1 row in set (0.02 sec)
 
+------------------+-------+
| Variable_name    | Value |
+------------------+-------+
| ngram_token_size | 2     |
+------------------+-------+
1 row in set (0.03 sec)

2. 数据准备

-- mysql 于全文检索的demo

mysql> CREATE TABLE `articles` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `title` varchar(50) DEFAULT NULL COMMENT '主题',
  `content` longtext NOT NULL COMMENT '内容',
  PRIMARY KEY (`id`),
  FULLTEXT KEY `title_content_index` (`content`,`title`) /*!50100 WITH PARSER `ngram` */ 
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8;
Query OK, 0 rows affected (0.20 sec)
 

mysql> INSERT INTO articles (`title`, `content`) VALUES
        ('如果','今生今世 永不再将你想起 
除了
除了在有些个
因落泪而湿润的夜里 如果
如果你愿意'),
        ('爱情','有一天路标迁了希望你能从容
有一天桥墩断了希望你能渡越
有一天栋梁倒了希望你能坚强
有一天期待蔫了希望你能理解'),
        ('远和近','你 一会看我
一会看云
我觉得
你看我时很远
你看云时很近'),
        ('断章','你站在桥上看风景,
看风景人在楼上看你。
明月装饰了你的窗子,
你装饰了别人的梦。'),
        ('独语','我向你倾吐思念
你如石像
沉默不应
如果沉默是你的悲抑
你知道这悲抑
最伤我心');

Query OK, 5 rows affected (0.08 sec)
Records: 5  Duplicates: 0  Warnings: 0
 
mysql> SELECT * from articles where match(content, title) against('风景' in  NATURAL LANGUAGE MODE) LIMIT 10;
+----+--------+--------------------------------------------------------------------------------------------------------------------------+
| id | title  | content                                                                                                                  |
+----+--------+--------------------------------------------------------------------------------------------------------------------------+
| 10 | 断章 |  你站在桥上看风景,
看风景人在楼上看你。
明月装饰了你的窗子,
你装饰了别人的梦。 |
+----+--------+--------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.02 sec)

3. 开始表演

  • 自然语言模式(NATURAL LANGUAGE MODE)

自然语言模式是MySQL 默认的全文检索模式。自然语言模式不能使用操作符,不能指定关键词必须出现或者必须不能出现等复杂查询。

  • 布隆模式(BOOLEAN MODE)

BOOLEAN模式可以使用操作符,可以支持指定关键词必须出现或者必须不能出现或者关键词的权重高还是低等复杂查询。

  • 查询扩展(QUERY EXPANSION)

查询的结果不仅匹配出结果同时可以联想出其他你需要的结果。(类似关联查询,但是官网推荐仅支持短语查询 否则会出现很多脏数据)

-- 自然语言模式(NATURAL LANGUAGE MODE)查询并得到评分

mysql> SELECT id, title, MATCH ( content, title ) against ( '风景' IN NATURAL LANGUAGE MODE ) AS score  FROM articles;
+----+-----------+--------------------+
| id | title     | score              |
+----+-----------+--------------------+
|  7 | 如果    |                  0 |
|  8 | 爱情    |                  0 |
|  9 | 远和近 |                  0 |
| 10 | 断章    | 0.9771181344985962 |
| 11 | 独语    |                  0 |
+----+-----------+--------------------+
5 rows in set (0.02 sec)

-- 布隆模式(BOOLEAN MODE) 可以组合查询

mysql> SELECT id, title  FROM articles where MATCH ( content, title ) against ( '+风景 -爱情' IN BOOLEAN MODE );
+----+--------+
| id | title  |
+----+--------+
| 10 | 断章 |
+----+--------+
1 row in set (0.01 sec)

-- 查询扩展(QUERY EXPANSION) 可以联想出其他结果 
mysql> SELECT id, title  FROM articles where MATCH ( content, title ) against ( '风景' WITH QUERY EXPANSION );
+----+--------+
| id | title  |
+----+--------+
| 10 | 断章 |
| 11 | 独语 |
+----+--------+
2 rows in set (0.02 sec)

4. 分词引擎

目前官网 MeCab Full-Text Parser 有支持日语的分词插件(可以更好的理解语义)

内置的 full-text parser 因为英文中单词的边界默认是空格,所以在处理英文文本时可以简单的使用空格作为分隔符。但是在处理中文时需要理解语义的基础上进行有效的分词,所以在处理中文、日文、韩文MySQL 提供了 ngram full-text (本文的配置就是 基于ngram的中文分词)

总结

优点

  • 对比 like 查询效率有提升(具体提升的测试没有做)
  • 全文搜索可以同时对多个字段做索引,like只能对单一字段搜索

对于中文的分词可能需要在理解语义的基础上才能有效的分词;比如上文中的 你好世界(hello world)对于英文按空格切分就可以,中文则需要理解语义的基础才能分成 你好/世界。

这里分享一下python中jieba分词,有助于理解中文分词的魅力

结巴分词利用一个中文词库,通过词库计算汉字之间构成词语的关联概率,所以通过计算汉字之间的概率,就可以形成分词的结果。

In [1]: import jieba

In [2]: jieba.lcut("你好世界")
Building prefix dict from the default dictionary ...
Dumping model to file cache /var/folders/st/b16fyn3s57x_5vszjl599njw0000gn/T/jieba.cache
Loading model cost 0.937 seconds.
Prefix dict has been built successfully.
Out[2]: ['你好', '世界']

In [3]: jieba.lcut("hello world")
Out[3]: ['hello', ' ', 'world']

对于一般的项目mysql的全文索引可以解决80%的需求,它可以较为完美的支持中文的检索、自动分词、结果排序、组合查询等功能;但性能应该是瓶颈,Elastissearch可以友好的实现全文检索。

全文索引不能达到like的效果,连着的语句会因为分词形成多个词语。

参考资料

Mysql fulltext

以上就是MySQL 全文检索的使用示例的详细内容,更多关于MySQL 全文检索的使用的资料请关注三水点靠木其它相关文章!

MySQL 相关文章推荐
MySQL创建索引需要了解的
Apr 08 MySQL
Mysql MVCC机制原理详解
Apr 20 MySQL
MySQL 使用自定义变量进行查询优化
May 14 MySQL
Unity连接MySQL并读取表格数据的实现代码
Jun 20 MySQL
浅谈mysql增加索引不生效的几种情况
Jun 23 MySQL
一文弄懂MySQL中redo log与binlog的区别
Feb 15 MySQL
MySQL高级进阶sql语句总结大全
Mar 16 MySQL
MySQL日期时间函数知识汇总
Mar 17 MySQL
浅谈redis的过期时间设置和过期删除机制
Mar 18 MySQL
实战 快速定位MySQL的慢SQL
Mar 22 MySQL
MySQL安装失败的原因及解决步骤
Jun 14 MySQL
MySQL中正则表达式(REGEXP)使用详解
Jul 07 MySQL
MySQL 常见的数据表设计误区汇总
Jun 07 #MySQL
浅谈MySQL next-key lock 加锁范围
MySQL为id选择合适的数据类型
MySQL单表千万级数据处理的思路分享
Jun 05 #MySQL
MySQL 时间类型的选择
Jun 05 #MySQL
MySQL索引失效的典型案例
Jun 05 #MySQL
MySQL库表名大小写的选择
Jun 05 #MySQL
You might like
phpMyAdmin 安装教程全攻略
2007/03/19 PHP
php格式化电话号码的方法
2015/04/24 PHP
codeigniter实现get分页的方法
2015/07/10 PHP
php中二分法查找算法实例分析
2016/09/22 PHP
兼容ie和firefox js关闭代码
2008/12/11 Javascript
用js判断是否为360浏览器的实现代码
2015/01/15 Javascript
jquery.form.js框架实现文件上传功能案例解析(springmvc)
2016/05/26 Javascript
前端弹出对话框 js实现ajax交互
2016/09/09 Javascript
JS常用算法实现代码
2016/11/14 Javascript
详解Vue.js——60分钟组件快速入门(上篇)
2016/12/05 Javascript
Node.js上传文件功能之服务端如何获取文件上传进度
2018/02/05 Javascript
JS实现二维数组横纵列转置的方法
2018/04/17 Javascript
Vue中使用Echarts仪表盘展示实时数据的实现
2020/11/01 Javascript
python任务调度实例分析
2015/05/19 Python
举例讲解Python中的Null模式与桥接模式编程
2016/02/02 Python
Python中的sort()方法使用基础教程
2017/01/08 Python
python遍历文件夹下所有excel文件
2018/01/03 Python
python如何压缩新文件到已有ZIP文件
2018/03/14 Python
python3写的简单本地文件上传服务器实例
2018/06/04 Python
Scrapy基于selenium结合爬取淘宝的实例讲解
2018/06/13 Python
简单了解python变量的作用域
2019/07/30 Python
Python API 操作Hadoop hdfs详解
2020/06/06 Python
详解px单位html5响应式方案
2018/03/08 HTML / CSS
Waterford英国官方网站:世界上最受欢迎的优质水晶品牌
2019/08/17 全球购物
质检员岗位职责
2013/12/17 职场文书
30年同学聚会邀请函
2014/01/25 职场文书
校长先进事迹材料
2014/02/01 职场文书
上班打牌检讨书
2014/02/07 职场文书
学校评语大全
2014/05/06 职场文书
产品委托授权书范本
2014/09/16 职场文书
2014年反洗钱工作总结
2014/11/22 职场文书
python自动化调用百度api解决验证码
2021/04/13 Python
使用canvas对video视频某一刻截图功能
2021/09/25 HTML / CSS
《仙剑客栈2》第一弹正式宣传片公开 年内发售
2022/04/07 其他游戏
使用vue判断当前环境是安卓还是IOS
2022/04/12 Vue.js
vue使用element-ui按需引入
2022/05/20 Vue.js