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 06 MySQL
Mysql服务添加 iptables防火墙策略的方案
Apr 29 MySQL
mysql 8.0.24版本安装配置方法图文教程
May 12 MySQL
MySQL 隔离数据列和前缀索引的使用总结
May 14 MySQL
MYSQL主从数据库同步备份配置的方法
May 26 MySQL
Navicat for MySQL的使用教程详解
May 27 MySQL
浅析MySQL如何实现事务隔离
Jun 26 MySQL
MySQL图形化管理工具Navicat安装步骤
Dec 04 MySQL
SQL语法CONSTRAINT约束操作详情
Jan 18 MySQL
Mysql使用全文索引(FullText index)的实例代码
Apr 03 MySQL
MySql中的json_extract函数处理json字段详情
Jun 05 MySQL
一文解答什么是MySQL的回表
Aug 05 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
php转换颜色为其反色的方法
2015/04/27 PHP
php基于jquery的ajax技术传递json数据简单实例
2016/04/15 PHP
php根据年月获取当月天数及日期数组的方法
2016/11/30 PHP
PHP中的日期时间处理利器实例(Carbon)
2017/06/09 PHP
PHP使用CURL实现下载文件功能示例
2019/06/03 PHP
经常用到的JavasScript事件的翻译
2007/04/09 Javascript
JavaScript 高级语法介绍
2009/06/15 Javascript
ajax不执行success回调而是执行了error回调
2012/12/10 Javascript
jquery高级编程的最佳实践详解
2014/03/23 Javascript
jquery获取tagName再进行判断
2014/05/29 Javascript
使用jQuery和Bootstrap实现多层、自适应模态窗口
2014/12/22 Javascript
jQuery表单验证功能实例
2015/08/28 Javascript
js实现文字超出部分用省略号代替实例代码
2016/09/01 Javascript
vue货币过滤器的实现方法
2017/04/01 Javascript
jQuery序列化后的表单值转换成Json
2017/06/16 jQuery
JS 中document.write()的用法和清空的原因浅析
2017/12/04 Javascript
JS中常用的消息框总结
2018/02/24 Javascript
微信小程序之侧边栏滑动实现过程解析(附完整源码)
2019/08/23 Javascript
在vue中使用jsonp进行跨域请求接口操作
2020/10/29 Javascript
python函数装饰器用法实例详解
2015/06/04 Python
python实现爬虫统计学校BBS男女比例之数据处理(三)
2015/12/31 Python
Python字典的基本用法实例分析【创建、增加、获取、修改、删除】
2019/03/05 Python
python如何删除文件中重复的字段
2019/07/16 Python
django使用django-apscheduler 实现定时任务的例子
2019/07/20 Python
详解使用PyInstaller将Pygame库编写的小游戏程序打包为exe文件
2019/08/23 Python
Python 3.8正式发布重要新功能一览
2019/10/17 Python
python飞机大战pygame游戏背景设计详解
2019/12/17 Python
python实现井字棋小游戏
2020/03/04 Python
英国在线发型和美容产品商店:Beauty Cutie
2019/04/27 全球购物
营业员演讲稿
2013/12/30 职场文书
《郑和远航》教学反思
2014/04/16 职场文书
商务日语专业的自荐信
2014/05/23 职场文书
网球场地租赁协议范本
2014/10/07 职场文书
写给女朋友的保证书
2015/05/09 职场文书
【超详细】八大排序算法的各项比较以及各自特点
2021/03/31 Python
宝塔更新Python及Flask项目的部署
2022/04/11 Python