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 05 MySQL
MySQL入门命令之函数-单行函数-流程控制函数
Apr 05 MySQL
MySQL主从复制断开的常用修复方法
Apr 07 MySQL
解决MySQL存储时间出现不一致的问题
Apr 28 MySQL
MySQL大小写敏感的注意事项
May 24 MySQL
MySQL 如何设计统计数据表
Jun 15 MySQL
Centos7中MySQL数据库使用mysqldump进行每日自动备份的编写
Aug 02 MySQL
教你如何让spark sql写mysql的时候支持update操作
Feb 15 MySQL
一文了解MySQL二级索引的查询过程
Feb 24 MySQL
Windows 64位 安装 mysql 8.0.28 图文教程
Apr 19 MySQL
Mysql 文件配置解析介绍
May 06 MySQL
分享很少见很有用的SQL功能CORRESPONDING
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
dede3.1分页文字采集过滤规则详说(图文教程)
2007/04/03 PHP
PHP 的异常处理、错误的抛出及回调函数等面向对象的错误处理方法
2012/12/07 PHP
解析如何通过PHP函数获取当前运行的环境 来进行判断执行逻辑(小技巧)
2013/06/25 PHP
使用PHP实现蜘蛛访问日志统计
2013/07/05 PHP
提高PHP编程效率的方法
2013/11/07 PHP
XHProf报告字段含义的解析
2016/05/17 PHP
JS与框架页的操作代码
2010/01/17 Javascript
jQuery动态添加删除select项(实现代码)
2013/09/03 Javascript
javascript使用数组的push方法完成快速排序
2014/09/15 Javascript
浅谈JavaScript中运算符的优先级
2015/07/07 Javascript
JS中的hasOwnProperty()、propertyIsEnumerable()和isPrototypeOf()
2016/08/11 Javascript
bootstrap table复杂操作代码
2016/11/01 Javascript
微信小程序实战之自定义抽屉菜单(7)
2017/04/18 Javascript
vue的基本用法与常见指令
2017/08/15 Javascript
如何使用CSS3和JQuery easing 插件制作绚丽菜单
2019/06/18 jQuery
vue组件是如何解析及渲染的?
2021/01/13 Vue.js
[51:43]OG vs LGD 2018国际邀请赛淘汰赛BO3 第五场 8.26
2018/08/30 DOTA
python抓取网页图片示例(python爬虫)
2014/04/27 Python
Python的Django框架中URLconf相关的一些技巧整理
2015/07/18 Python
Python网站验证码识别
2016/01/25 Python
Python实现连接postgresql数据库的方法分析
2017/12/27 Python
Windows下将Python文件打包成.EXE可执行文件的方法
2018/08/03 Python
在Python 中实现图片加框和加字的方法
2019/01/26 Python
解决django中ModelForm多表单组合的问题
2019/07/18 Python
C++如何引用一个已经定义过的全局变量
2014/08/25 面试题
Internet体系结构
2014/12/21 面试题
奥巴马演讲稿
2014/01/08 职场文书
中层干部竞争上岗演讲稿
2014/01/13 职场文书
2014年世界艾滋病日宣传活动总结
2014/11/18 职场文书
2014年人事科工作总结
2014/11/19 职场文书
2014年煤矿工作总结
2014/11/24 职场文书
我在伊朗长大观后感
2015/06/16 职场文书
借钱欠条怎么写
2015/07/03 职场文书
开学第一周日记(三篇范文)
2019/08/23 职场文书
利用Matlab绘制各类特殊图形的实例代码
2021/07/16 Python
Mysql如何实现不存在则插入,存在则更新
2022/03/25 MySQL