Mysql实现全文检索、关键词跑分的方法实例

一、前言

今天一个同事问我,如何使用 Mysql 实现类似于 ElasticSearch 的全文检索功能,并且对检索关键词跑分?我当时脑子里立马产生了疑问?为啥不直接用es呢?简单好用还贼快。但是听他说,数据量不多,客户给的时间非常有限,根本没时间去搭建es,所以还是看一下 Mysql 的全文检索功能吧!

MySQL 从 5.7.6 版本开始,MySQL就内置了ngram全文解析器,用来支持中文、日文、韩文分词。在 MySQL 5.7.6 版本之前,全文索引只支持英文全文索引,不支持中文全文索引,需要利用分词器把中文段落预处理拆分成单词,然后存入数据库。本篇文章测试的时候,采用的 Mysql 5.7.6 ,InnoDB数据库引擎。mysql全文检索

二、全文解析器ngram

ngram就是一段文字里面连续的n个字的序列。ngram全文解析器能够对文本进行分词,每个单词是连续的n个字的序列。
例如,用ngram全文解析器对“你好世界”进行分词:

n=1: '你', '好', '世', '界'
n=2: '你好', '好世', '世界'
n=3: '你好世', '好世界'
n=4: '你好世界'

MySQL 中使用全局变量 ngram_token_size 来配置 ngram 中 n 的大小,它的取值范围是1到10,默认值是 2。通常ngram_token_size设置为要查询的单词的最小字数。如果需要搜索单字,就要把ngram_token_size设置为 1。在默认值是 2 的情况下,搜索单字是得不到任何结果的。因为中文单词最少是两个汉字,推荐使用默认值 2。

咱们看一下Mysql默认的ngram_token_size大小:

show variables like 'ngram_token_size'

ngram_token_size 变量的两种设置方式:

1、启动mysqld命令时指定

mysqld --ngram_token_size=2

2、修改mysql配置文件

[mysqld]
ngram_token_size=2

三、全文索引

以某文书数据为例,新建数据表 t_wenshu ,并且针对文书内容字段创建全文索引,导入10w条测试数据。

1、建表时创建全文索引

CREATE TABLE `t_wenshu` (
 `province` varchar(255) DEFAULT NULL,
 `caseclass` varchar(255) DEFAULT NULL,
 `casenumber` varchar(255) DEFAULT NULL,
 `caseid` varchar(255) DEFAULT NULL,
 `types` varchar(255) DEFAULT NULL,
 `title` varchar(255) DEFAULT NULL,
 `content` longtext,
 `updatetime` varchar(255) DEFAULT NULL,
 FULLTEXT KEY `content` (`content`) WITH PARSER `ngram`
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

2、通过 alter table 方式

ALTER TABLE t_wenshu ADD FULLTEXT INDEX content_index (content) WITH PARSER ngram;

3、通过 create index 方式

CREATE FULLTEXT INDEX content_index ON t_wenshu (content) WITH PARSER ngram;

四、检索模式

自然语言检索

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

布尔检索

(IN BOOLEAN MODE)剔除一半匹配行以上都有的词,例如,每行都有this这个词的话,那用this去查时,会找不到任何结果,这在记录条数特别多时很有用,原因是数据库认为把所有行都找出来是没有意义的,这时,this几乎被当作是stopword(中断词);布尔检索模式可以使用操作符,可以支持指定关键词必须出现或者必须不能出现或者关键词的权重高还是低等复杂查询。

● IN BOOLEAN MODE的特色:
      ·不剔除50%以上符合的row。
      ·不自动以相关性反向排序。
      ·可以对没有FULLTEXT index的字段进行搜寻,但会非常慢。
      ·限制最长与最短的字符串。
      ·套用Stopwords。

● 搜索语法规则:
     +   一定要有(不含有该关键词的数据条均被忽略)。
     -   不可以有(排除指定关键词,含有该关键词的均被忽略)。
     >   提高该条匹配数据的权重值。
     <   降低该条匹配数据的权重值。
     ~   将其相关性由正转负,表示拥有该字会降低相关性(但不像-将之排除),只是排在较后面权重值降低。
     *   万用字,不像其他语法放在前面,这个要接在字符串后面。
     " " 用双引号将一段句子包起来表示要完全相符,不可拆字。

查询扩展检索

注释:(WITH QUERY EXPANSION)由于查询扩展可能带来许多非相关性的查询,谨慎使用!

五、检索查询

1)查询 content 中包含“盗窃罪”的记录,查询语句如下

select caseid,content, MATCH ( content) AGAINST ('盗窃罪') as score from t_wenshu where MATCH ( content) AGAINST ('盗窃罪' IN NATURAL LANGUAGE MODE)

2)查询 content 中包含“寻衅滋事”的记录,查询语句如下

select caseid,content, MATCH ( content) AGAINST ('寻衅滋事') as score from t_wenshu where MATCH ( content) AGAINST ('寻衅滋事' IN NATURAL LANGUAGE MODE) ;

3)单个汉字,查询 content 中包含“我”的记录,查询语句如下

select caseid,content, MATCH ( content) AGAINST ('我') as score from t_wenshu where MATCH ( content) AGAINST ('我' IN NATURAL LANGUAGE MODE) ;

备注:因为设置的全局变量 ngram_token_size 的值为 2。如果想查询单个汉字,需要在配置文件 my.ini 中修改 ngram_token_size = 1 ,并重启 mysqld 服务,此处不做尝试了。

4)查询字段 content 中包含 “危险驾驶”和“寻衅滋事”的语句如下:

select caseid,content, MATCH (content) AGAINST ('+危险驾驶 +寻衅滋事') as score from t_wenshu where MATCH (content) AGAINST ('+危险驾驶 +寻衅滋事' IN BOOLEAN MODE);

5)查询字段 content 中包含 “危险驾驶”,但不包含“寻衅滋事”的语句如下:

select caseid,content, MATCH (content) AGAINST ('+危险驾驶 -寻衅滋事') as score from t_wenshu where MATCH (content) AGAINST ('+危险驾驶 -寻衅滋事' IN BOOLEAN MODE);

6)查询字段 conent 中包含“危险驾驶”或者“寻衅滋事”的语句如下:

select caseid,content, MATCH (content) AGAINST ('危险驾驶 寻衅滋事') as score from t_wenshu where MATCH (content) AGAINST ('危险驾驶 寻衅滋事' IN BOOLEAN MODE);

六、总结

1)使用 Mysql 全文索引之前,搞清楚各版本支持情况;

2)全文索引比 like + % 快 N 倍,但是可能存在精度问题;

3)如果需要全文索引的是大量数据,建议先添加数据,再创建索引;

4)对于中文,可以使用 MySQL 5.7.6 之后的版本,或者 Sphinx、Lucene 等第三方的插件;

5)MATCH()函数使用的字段名,必须要与创建全文索引时指定的字段名一致,且只能是同一个表的字段不能跨表;

到此这篇关于Mysql实现全文检索、关键词跑分的文章就介绍到这了,更多相关Mysql全文检索、关键词跑分内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • mysql 全文检索中文解决方法及实例代码

    mysql 全文检索中文解决方法             最近公司项目要求这样的功能,在数据库中检索中文,很是棘手,上网查询下资料,找的类似文章,这里及记录下,希望能帮助到大家, 实例代码:    <?php /* mysql全文检索中文解决方案! */ error_reporting(E_ERROR | E_WARNING | E_PARSE); ini_set('display_errors', '1'); //数据库支持 class SaeMysql{ //phpmysql操作类 } $D

  • 深度解析MySQL 5.7之中文全文检索

    前言 其实全文检索在MySQL里面很早就支持了,只不过一直以来只支持英文.缘由是他从来都使用空格来作为分词的分隔符,而对于中文来讲,显然用空格就不合适,需要针对中文语义进行分词.这不,从MySQL 5.7开始,MySQL内置了ngram全文检索插件,用来支持中文分词,并且对MyISAM和InnoDB引擎有效. 在使用中文检索分词插件ngram之前,先得在MySQL配置文件里面设置他的分词大小,比如, [mysqld] ngram_token_size=2 这里把分词大小设置为2.要记住,分词的S

  • PHP+MySQL+sphinx+scws实现全文检索功能详解

    本文实例讲述了PHP+MySQL+sphinx+scws实现全文检索功能.分享给大家供大家参考,具体如下: 我的个人环境是PHP7.1+MariaDB10.1.23 下载安装资源包 sphinx地址 http://sphinxsearch.com/downloads/release/ PHP的sphinx扩展下载 http://pecl.php.net/package/sphinx SCWS 下载地址 http://www.xunsearch.com/scws/download.php SCWS

  • Mysql实现全文检索、关键词跑分的方法实例

    一.前言 今天一个同事问我,如何使用 Mysql 实现类似于 ElasticSearch 的全文检索功能,并且对检索关键词跑分?我当时脑子里立马产生了疑问?为啥不直接用es呢?简单好用还贼快.但是听他说,数据量不多,客户给的时间非常有限,根本没时间去搭建es,所以还是看一下 Mysql 的全文检索功能吧! MySQL 从 5.7.6 版本开始,MySQL就内置了ngram全文解析器,用来支持中文.日文.韩文分词.在 MySQL 5.7.6 版本之前,全文索引只支持英文全文索引,不支持中文全文索引

  • mysql滑动订单问题原理与解决方法实例分析

    本文实例讲述了mysql滑动订单问题原理与解决方法.分享给大家供大家参考,具体如下: 先根据以下代码来创建表MonthlyOrders并导入一定的数据 CREATE TABLE MonthlyOrders( ordermonth DATE, ordernum INT UNSIGNED, PRIMARY KEY (ordermonth) ); INSERT INTO MonthlyOrders SELECT '2010-02-01',23; INSERT INTO MonthlyOrders SE

  • MySQL Index Condition Pushdown(ICP)性能优化方法实例

    一 概念介绍 Index Condition Pushdown (ICP)是MySQL 5.6 版本中的新特性,是一种在存储引擎层使用索引过滤数据的一种优化方式. a 当关闭ICP时,index 仅仅是data access 的一种访问方式,存储引擎通过索引回表获取的数据会传递到MySQL Server 层进行where条件过滤. b 当打开ICP时,如果部分where条件能使用索引中的字段,MySQL Server 会把这部分下推到引擎层,可以利用index过滤的where条件在存储引擎层进行

  • Mysql删除数据以及数据表的方法实例

    在Mysql 中删除数据以及数据表非常的容易,但是需要特别小心,因为一旦删除所有数据都会消失. 删除数据 删除表内数据,使用delete关键字. 删除指定条件的数据 删除用户表内id 为1 的用户: delete from User where id = 1; 删除表内所有数据 删除表中的全部数据,表结构不变. 对于 MyISAM 会立刻释放磁盘空间,InnoDB 不会释放磁盘空间. delete from User; 释放磁盘空间 optimize table User; 删除数据表 删除数据

  • mysql按照自定义(指定顺序)排序的方法实例

    目录 一.mysql中实现指定排序需求 二.解决方案 1:自定义排序实现 01. case when 转换实现自定义排序: 02:mysql排序函数filed 实现自定义排序(推荐): 03:函数locate 实现自定义排序: 04:函数lnstr 实现自定义排序: 05:利用数据字典实现自定义排序: 总结 一.mysql中实现指定排序需求 一般情况下,我们排序都是直接利用 order by 字段 asc/desc;但是如果要排序的字段数据格式并不能直接实现,或者说我们需要指定的顺序且没有什么规

  • MySQL一劳永逸永久支持输入中文的方法实例

    目录 1.在C盘中,在查看中将隐藏的项目放出,点开ProgramData 2.在M字母的区域内找到MySQL 3.选择MySQL Server 5.7 4.创建my.ini副本防止出错(直接复制粘贴),点进my.ini 5.带#的都是注释,不必理睬,直接找到[client],添加以下内容 6.再找到[mysqld],添加以下语句 7.保存后,找到服务重启(关闭窗口,重点图标不行!!!) 8.在弹出的框中,找到MySQL57重启 总结 1.在C盘中,在查看中将隐藏的项目放出,点开ProgramDa

  • 查找MySQL中查询慢的SQL语句方法

    如何在mysql查找效率慢的SQL语句呢?这可能是困然很多人的一个问题,MySQL通过慢查询日志定位那些执行效率较低的SQL 语句,用--log-slow-queries[=file_name]选项启动时,mysqld 会写一个包含所有执行时间超过long_query_time 秒的SQL语句的日志文件,通过查看这个日志文件定位效率较低的SQL .下面介绍MySQL中如何查询慢的SQL语句 一.MySQL数据库有几个配置选项可以帮助我们及时捕获低效SQL语句 1,slow_query_log 这

  • MySQL百万级数据量分页查询方法及其优化建议

    数据库SQL优化是老生常谈的问题,在面对百万级数据量的分页查询,又有什么好的优化建议呢?下面将列举了一些常用的方法,供大家参考学习! 方法1: 直接使用数据库提供的SQL语句 语句样式: MySQL中,可用如下方法: SELECT * FROM 表名称 LIMIT M,N 适应场景: 适用于数据量较少的情况(元组百/千级) 原因/缺点: 全表扫描,速度会很慢 且 有的数据库结果集返回不稳定(如某次返回1,2,3,另外的一次返回2,1,3). Limit限制的是从结果集的M位置处取出N条输出,其余

  • MySQL实现MYISAM表批量压缩的方法

    本文实例讲述了MySQL实现MYISAM表批量压缩的方法.分享给大家供大家参考,具体如下: 关于对MYISAM表的压缩,可以使用myisampack和myisamchk完成(myisampack完之后必须进行myisamchk才能使用压缩后的表,而且是只读的), 其详细地用法可以参考官方文档: http://dev.mysql.com/doc/refman/5.1/zh/client-side-scripts.html. 这两个操作需要谨慎使用,在压缩之前需要确认mysqld已关闭或者要压缩的表

  • 在MySQL字段中使用逗号分隔符的方法分享

    被分割的字段一定是有限而且数量较少的,我们不可能在一个字符串中存储无限多个字符 这个字段所属的表与这个字段关联的表,一定是一对多的关系 比如下面这个表结构所代表的content与tag这两个对象 复制代码 代码如下: mysql> SELECT * FROM content; +----+------+| id | tags | +----+------+| 1 | 1,2 | | 2 | 2,3 | +----+------+ 2 rows in set (0.01 sec) mysql>

随机推荐