mysql/mariadb 实现全文检索
为什么要使用全文检索
有很多业务都有根据某关键字或者某短语去模糊搜索结果的情况,比如文章或者博客标题,内容,等关键字搜索,或者根据多个词语组合搜索,比如搜索“nba 湖人 科比”找到匹配度最高的内容等,因此全文检索在各场景的应用还是很广的
都有哪些方式实现全文检索
就我个人实际项目应用中搭建以及落地的项目情况来说,早期主要用solr,后期主要用elasticsearch
,其实这些都是很不错的第三方全文检索应用,但是如果规模量级很小的项目,用这些就有点杀鸡用牛刀了,而且为了保证solr 或者es
高可用,一般都会进行集群搭建与维护,这就额外的增加了开发和部署以及维护成本,所以这里主要介绍一下中小项目下直接用mysql5.6+/mariadb10.0.6+
实现全文检索功能
如何用mysql实现全文检索
由于mariadb 全文检索模式需要适用Mroonga 存储引擎,但此引擎不支持事务,所以选择了择中方案,先调用分词器,将内存分解为自然语言分词,然后保存在一个独立字段中,本文只是创建了个测试表用来演示,暂不涉及分词器部分,后续篇章中会有独立介绍以及全部分词器代码项目demo 链接如下:
java字符串分词参考我另一篇文章《java应用集成HanLP进行中文自然语言分词详细完整案例以及demo》
like 方式
like 方式左关联like %xx 会导致索引失效,然后大部分业务都需要左右模糊匹配查询,因此大数据两情况下会造成极大性能耗费
match 方式(仅限于mysql >=5.6)
match 基于fulltext 索引机制需要查询字段必须先创建fulltext 索引,否则无法使用,而且一起查询的列也都必须一同做关联索引,不然一样无法使用
match 全文检索分为三种类型,如下:
1.自然语言搜索(IN NATURAL LANGUAGE MODE)
查询关键字表达式会被解析器分解为若干个单词,把每个单词匹配的行都查询出来。
2.布尔搜索 (IN BOOLEAN MODE) 查询关键字表达式中可以包含特定的修饰字符,通过修饰字符,来满足特殊的查询条件。
修饰符 | 说明 |
+ | 加号,结果中必需包含 |
- | 减号,结果中不能包含 |
空格,结果中,至少包含一个由空格连接的单词 | |
* | 星号,作为通配符匹配 |
3.查询扩展搜索(WITH QUERY EXPANSION)
使用场景以及语法demo
准备测试数据以及创建索引
注意:如果要同时查询多个字段的匹配情况,需要创建独立字段的索引以及多个字段一起的索引
比如我有title和body两个字,可能需要各自独立查询,也需要同时查询,那么就得创建独立索引的同时也要创建一起的关联索引,如下
查询对应匹配项数量
select count(*) from test where MATCH(title,body) AGAINST ('开发' IN BOOLEAN MODE)
查询含有’开发‘字样的匹配项行内容
select * from test where MATCH(title,body) AGAINST ('开发' IN BOOLEAN MODE)
查询匹配度
select MATCH(title,body) AGAINST ('+开发' IN BOOLEAN MODE) from test
查询含有’开发‘字样且不含有‘入门‘字样的匹配项行内容
select * from test where MATCH(title,body) AGAINST ('+开发 -入门' IN BOOLEAN MODE)
查询含有’世界’为开头的匹配项,和like’xx%’ 右匹配相同,比如如 lik*,表示可以是 lik,like,likes
select * from test where MATCH(title,body) AGAINST ('世界*' IN BOOLEAN MODE)
查询确切含有’入门课程‘字样短语的匹配项行内容
select * from test where MATCH(title,body) AGAINST ('"入门课程"' IN BOOLEAN MODE)