最近做項目遇到了一個需求,那就是對富文本消息列表增加一個搜索功能,輸入一個搜索條件可以同時對標題和富文本的內容進行搜索。
剛開始覺得很簡單,直接寫個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("<.*?>","")
搞定收工!!!