mysql模糊查询富文本的文本内容
最近做项目遇到了一个需求,那就是对富文本消息列表增加一个搜索功能,输入一个搜索条件可以同时对标题和富文本的内容进行搜索。
刚开始觉得很简单,直接写个sql语句判断一下就OK了,于是最开始我是这样写的:
select n.obj_id,n.title,n.thumbs,n.content,date_format(n.create_time,'%Y-%m-%d %H:%i:%s') create_time from t_dwshhcj_notifyinfo n,t_dwshhcj_company_info c where instr(n.visible_scope,c.childdwlx)>0 and c.obj_id = '56f891e5-b525-4b92-a4ba-a6cba97f7f40' and c.deleted='0' and n.deleted='0' and (instr(title,'test')>0 or instr(content,'test')>0)
当时觉得这样写肯定没问题,但是一经测试,问题来了;因为content字段保存的是整个富文本信息,除了文本内容,还有html元素,行内样式,如果有图片的话还包含图片的id等信息;这样的话,在搜索时就会搜索出一些标题和内容都不相关的列表。
针对这一问题我开始尝试解决的思路;
首先想到的就是使用mysql的正则替换,经过多方面的查阅资料才发现,mysql 支持的正则非常简单,而且低版本的mysql不具备正则替换的功能,mysql的正则只能类似于like 语句,用来对特定字符的匹配,并不能做到替换的功能。
-- 查找name字段中以'st'为开头的所有数据: SELECT name FROM person_tbl WHERE name REGEXP '^st'; -- 查找name字段中以'ok'为结尾的所有数据: SELECT name FROM person_tbl WHERE name REGEXP 'ok$'; -- 查找name字段中包含'mar'字符串的所有数据: SELECT name FROM person_tbl WHERE name REGEXP 'mar'; -- 查找name字段中以元音字符开头或以'ok'字符串结尾的所有数据: SELECT name FROM person_tbl WHERE name REGEXP '^[aeiou]|ok$';
如果将正则匹配作为结果,则是这样的:
很明显,要想通过mysql的正则来实现对纯文本的模糊查询是不行的。当时的我一脸蒙圈,心想这可咋整。
然后,就在那一瞬间,就那么一瞬间,我脑袋里灵光一闪,既然mysql正则不行,但是java的正则是可以的啊,于是我突然看到了光明,接着编准备动手干。
首先,在富文本的消息表中再新增一个字段,名字叫text_content,专门用来保存纯文本信息;
其次,在保存content的时候将content中的纯文本提取出来并保存到text_content;
最后,sql语句中的content换成text_content,也就是使用text_content来代替content来进行模糊查询。
select n.obj_id,n.title,n.thumbs,n.content,date_format(n.create_time,'%Y-%m-%d %H:%i:%s') create_time from t_dwshhcj_notifyinfo n,t_dwshhcj_company_info c where instr(n.visible_scope,c.childdwlx)>0 and c.obj_id = '56f891e5-b525-4b92-a4ba-a6cba97f7f40' and c.deleted='0' and n.deleted='0' and (instr(title,'test')>0 or instr(text_content,'test')>0)
提取纯文本使用以下方法去掉所有html元素;
String textContent = content.replaceAll("<.*?>","")
搞定收工!!!