百度二面,MySQL 怎么做权重搜索?

考虑这样一个搜索需求,有一个 MySQL 表,表中很多个列存放着不同的内容,希望用户通过关键词进行搜索的时候,能够模糊匹配多个列,比如有 t1 列、t2 列、t3 列,同时还希望 t1 列的匹配权重最高,t3 列的匹配权重最低。简单说就是如果有一个关键词同时出现在记录 A 的 t1 列 和里记录 B 的 t2 列,那么记录 A 应该优先展示,排序是在前面的。

注意这里是 MySQL,不是 ES,搜索引擎做这种搜索需求当然得天独厚,但是这种在 MySQL 中进行权重搜索的需求也不是没有,业务初期数据量还不大的时候大概率不会考虑上 ES,这时候在 MySQL 中先简单跑通逻辑才是最重要的。

思考下该如何做?

模糊匹配

首先模糊匹配大家最常用的就是 like

SELECT * FROM test 
WHERE t1 LIKE '%标题%' 
 or t2 LIKE '%内容%' 
 or t3 LIKE '%注释%''

当只需要简单的模式匹配时 like 确实往往是更好的选择。而在需要进行复杂匹配,如同一字段中包含多个模式,进行分组匹配等,REGEXP 则表现更为突出,Mysql 支持对列的正则表达式方式查询,使用方式如下:

SELECT  * FROM test 
WHERE t1 regexp '标题'
 or t2 regexp '内容' 
 or t3 regexp '注释'

权重搜索

权重搜索涉及到几个 Mysql 函数。

  • LOCATE('标题', test.t1) : 查询 "标题" 在 test.t1 列出现的位置,0 表示未找到。否则返回 坐标位置,坐标位置从 1 开始。

  • IF( 表达式, 1, 0):判断表达式结果,TRUE 则返回 1,FALSE 则返回 0

下面我们来看如何基于这两个函数来实现文章开头的需求:

SELECT  *, ( 
    IF(LOCATE('标题',test.t1), 1, 0) 
     + IF(LOCATE('内容',test.t2) , 1, 0) 
     + IF(LOCATE('注释',test.t3) , 1, 0) 
 ) AS weight 
FROM test 
WHERE test.t1 regexp '标题'
 or test.t2 regexp '内容' 
 or test.t3 regexp '注释' 
order by weight desc 

上面的查询中,每个关键词的权重都是 1,所以,在这 t1\t2\t3 三列中,关键词出现次数最多的记录将出现在搜索结果的第一位。

如果权重增加,那么权重高的关键词将会影响排序规则。如下例子,将 t1 列的搜索权重改为 7:

SELECT  *, ( 
    IF(LOCATE('标题',test.t1), 7, 0) 
     + IF(LOCATE('内容',test.t2) , 2, 0) 
     + IF(LOCATE('注释',test.t3) , 1, 0) 
 ) AS weight 
FROM test 
WHERE test.t1 regexp '标题'
 or test.t2 regexp '内容' 
 or test.t3 regexp '注释' 
order by weight desc 
相关推荐
数据的世界0112 分钟前
SQL使用视图
数据库·sql
T.O.P1121 分钟前
InnoDB存储引擎对MVCC的实现
数据库·oracle
SelectDB技术团队1 小时前
计算效率提升 10 倍,存储成本降低 60%,灵犀科技基于 Apache Doris 建设统一数据服务平台
大数据·数据库·数据仓库·数据分析·doris
firepation1 小时前
基于SpringBoot学生就业管理系统
java·spring boot·mysql·源码·课程设计
落霞与孤鹭齐飞。。2 小时前
记忆旅游系统|Java|SSM|VUE| 前后端分离
java·mysql·毕业设计·课程设计
追风赶月、2 小时前
【MySQL】表的基本查询
数据库·mysql
高思宇3 小时前
Oracle删除归档日志
数据库·windows·oracle
Ultipa3 小时前
图数据库 | 17、高可用分布式设计(上)
数据库·分布式
深鱼~3 小时前
香橙派Zero3上搭建Code Server开发环境轻量级远程开发新体验
服务器·数据库·面试·职场和发展·智能手机
yuanbenshidiaos3 小时前
MYSQL---------支持数据类型
数据库·mysql