本文技术栈 Spring Boot Mysql
中文分词搜索可以用很多实现方式,其中
ES
应该是比较快捷能够实现,但考虑到数据同步,业务复杂度,查询条件等问题,决定还是用 mysql 去实现。
中文分词工具
我这里随便找了一个分词工具 ansj_seg
<dependency>
<groupId>org.ansj</groupId>
<artifactId>ansj_seg</artifactId>
<version>5.1.1</version>
</dependency>
同时借助 Hutool 的能力,即可完成分词
// 根据用户引入的分词引擎jar,自动创建对应的分词引擎对象
Result result = TokenizerUtil.createEngine().parse(query.getKeyword());
Sql 如何实现分词查询
使用正则表达式
select * from project p
where
p.name REGEXP CONCAT_WS('|',<foreach collection="param2.keywords" item="item" separator=",">#{item}</foreach>)
传入的 keyword =上海迪士尼摩天轮
组合后的 sql
大概为
select * from project p where p.name REGEXP '上海|迪士尼|摩天轮';
Sql 如何实现相关性排序
在 ES
中有个重要的能力,那就是查找时会有个相关性指数,排序会根据次指数返回,但 Mysql 却没这个指数。此时就有可能出现有一条记录的 name
与 keyword
完全相等,但查询的时候却不在第一个结果中。我们该如何操作呢
如果你是 8.0.4
那么恭喜你,直接可以使用 REGEXP_COUNT
SELECT column_name
FROM table_name
WHERE column_name REGEXP 'your_regex_pattern'
ORDER BY REGEXP_COUNT(column_name, 'your_regex_pattern') DESC;
如果你是低版本,那么可以使用
SELECT column_name
FROM table_name
WHERE column_name REGEXP 'your_regex_pattern'
ORDER BY LENGTH(column_name) - LENGTH(REPLACE(column_name, 'your_regex_pattern', '')) DESC;