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 Show Profile
Apr 05 MySQL
MySQL8.0.24版本Release Note的一些改进点
Apr 22 MySQL
MySQL 全文索引使用指南
May 25 MySQL
Mysql 用户权限管理实现
May 25 MySQL
一文读懂navicat for mysql基础知识
May 31 MySQL
MySQL中utf8mb4排序规则示例
Aug 02 MySQL
mysql聚集索引、辅助索引、覆盖索引、联合索引的使用
Feb 12 MySQL
MySQL 执行数据库更新update操作的时候数据库卡死了
May 02 MySQL
Mysql将字符串按照指定字符分割的正确方法
May 30 MySQL
MySQL事务的ACID特性以及并发问题方案
Jul 15 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
php守护进程 加linux命令nohup实现任务每秒执行一次
2011/07/04 PHP
php检测数组长度函数sizeof与count用法
2014/11/17 PHP
PHP中mysql_field_type()函数用法
2014/11/24 PHP
php的instanceof和判断闭包Closure操作示例
2020/01/26 PHP
合并table相同单元格的jquery插件分享(很精简)
2011/06/20 Javascript
JavaScript中的property和attribute介绍
2011/12/26 Javascript
jquery获取html元素的绝对位置和相对位置的方法
2014/06/20 Javascript
KnockoutJS 3.X API 第四章之表单textInput、hasFocus、checked绑定
2016/10/11 Javascript
JS常用函数和常用技巧小结
2016/10/15 Javascript
JavaScript中for循环的几种写法与效率总结
2017/02/03 Javascript
javascript中mouseenter与mouseover的异同
2017/06/06 Javascript
node.js用fs.rename强制重命名或移动文件夹的方法
2017/12/27 Javascript
手把手教你写一个微信小程序(推荐)
2018/10/17 Javascript
JavaScript 严格模式(use strict)用法实例分析
2020/03/04 Javascript
jquery实现手风琴案例
2020/05/04 jQuery
vue自定义指令和动态路由实现权限控制
2020/08/28 Javascript
Django imgareaselect手动剪切头像实现方法
2015/05/26 Python
Python常见工厂函数用法示例
2018/03/21 Python
Python随机生成身份证号码及校验功能
2018/12/04 Python
Python 中Django验证码功能的实现代码
2019/06/20 Python
Python制作微信好友背景墙教程(附完整代码)
2019/07/17 Python
Django 用户认证组件使用详解
2019/07/23 Python
Python破解BiliBili滑块验证码的思路详解(完美避开人机识别)
2020/02/17 Python
python简单实现最大似然估计&scipy库的使用详解
2020/04/15 Python
如何查看python关键字
2021/01/17 Python
HTML5中form如何关闭自动完成功能的方法
2018/07/02 HTML / CSS
英国和爱尔兰最大的地毯零售商:Kukoon
2018/12/17 全球购物
Lime Crime官网:美国一家主打梦幻精灵系的彩妆品牌
2019/03/22 全球购物
工地宣传标语
2014/06/18 职场文书
高中运动会广播稿
2014/09/16 职场文书
置业顾问岗位职责
2015/02/09 职场文书
2015年八一建军节演讲稿
2015/03/19 职场文书
CSS 还能这样玩?奇思妙想渐变的艺术
2021/04/27 HTML / CSS
Java使用httpRequest+Jsoup爬取红蓝球号码
2021/07/02 Java/Android
JavaScript的Set数据结构详解
2022/02/18 Javascript
python如何为list实现find方法
2022/05/30 Python