前端時間公司內部開發了一個小項目,方便運維人員在線上傳查閱資料,其中搜索功能提出要實現 多關鍵字 結果高亮顯示。
剛好想到之前項目使用過IKAnalyzer語義分析實現詞雲的效果,剛好能用在這裏,於是有了以下思路:
1、創建一個list(數組、set都行);
2、加入整個搜索字條作爲基礎搜索條件;
3、走語義分析,拆分成小的詞組,list中沒有時加入;
4、遍歷出所有結果;
最後對返回的關鍵字全局替換成高亮顯示。
效果展示:
ps:項目框架使用的SSM
看下代碼,接口:
@RequestMapping("/search.json")
@ResponseBody
public Pagination<Article> search(@RequestParam(name="pageNo", defaultValue="1") Integer pageNo,
@RequestParam(name="pageSize", defaultValue="2") Integer pageSize,HttpServletRequest request){
Pagination<Article> page = new Pagination<>(0, pageSize,pageNo);
User user = TokenManager.getToken();
String username = user.getAccount();
String companyCode = companyEmployeeService.getCompanyByAccount(username);
Map map=new HashMap(16);
map.put("company_code",companyCode);
//用戶輸入的搜索字符串
String content=request.getParameter("content");
try {
if(StringUtils.isNotEmpty(content)){
//創建一個list用於存放切分的關鍵字,供前臺高亮顯示
List<String> fvs = new ArrayList<>();
//整個搜作詞條作爲默認關鍵字
fvs.add(content);
//創建IKAnalyzer實例,設置是否智能分詞,擴展詞典路徑,準備詞句拆分
MyIKConfig cfg = new MyIKConfig();
cfg.setUseSmart(true);
cfg.setMainDictionary("ext.dic");
IKSegmenter seg = new IKSegmenter(new StringReader(content),cfg);
Lexeme word = null;
String w = null;
//遍歷分詞,對於重複出現的分詞不加入list
while((word = seg.next()) != null){
w = word.getLexemeText();
//切片長度至少爲2
if(w.length()>1){
int nType = word.getLexemeType();
if (nType == 64) {
continue;
}
if(!fvs.contains(w)){
fvs.add(w);
}
}
}
//切分詞組加入查詢條件
map.put("fvs",fvs);
//獲取所有符合的文章
List<Article> articles = articleService.getSearchContent(map,null);
//分頁查詢
List<Article> pArticles = articleService.getSearchContent(map,page);
//將切分的關鍵字返回前端(想了半天直接搞了一個臨時字段存裏面了)
if(pArticles!=null && pArticles.size()>0){
pArticles.get(0).setIKWords(fvs);
}
page.setTotalCount(articles.size());
page.setTotalPages((int)Math.ceil((double)articles.size()/(double)pageSize));
page.setList(pArticles);
}
return page;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
Mapper:
<select id="getSearchContent" parameterType="map" resultType="com.swsc.racoon.entity.Article">
select distinct a.*,b.value as articleType from se_article a
left join se_knowledge_tree b on a.article_type=b.dcode
left join se_company_employee c on c.account =a.create_by
where a.status='2' and c.company_code = #{company_code}
<if test="content != null and content != ''">
AND (a.title like CONCAT('%',#{content},'%') or a.subtitle like CONCAT('%',#{content},'%'))
</if>
<if test="fvs !=null and fvs!=''">
and
<foreach collection="fvs" open="(" close=")" separator="or" item="item">
a.title like CONCAT('%',#{item},'%') or a.subtitle like CONCAT('%',#{item},'%')
</foreach>
</if>
order by a.upload_date desc
</select>
<if test="fvs !=null and fvs!=''">
and
<foreach collection="fvs" open="(" close=")" separator="or" item="item">
a.title like CONCAT('%',#{item},'%') or a.subtitle like CONCAT('%',#{item},'%')
</foreach>
</if>
這裏是Mybatis對於list的foreach循環,結構是 and ( (x like xx or x like xx) or (x like xx or x like xx) or (x like xx or x like xx) ..)
前端頁面:
高亮展示思路即獲取區域元素全局關鍵字替換
//獲取list拼接展示
$.ajax({
dataType: 'json',
type: 'POST',
url: "/admin/homePage/search.json",
data: {pageNo: pageNo, content:$("#s_content").val()},
success: function (data) {
var html = "";
//這裏是拼接html
$("#right").html(html);
for(ele of data.list[0].ikwords){
hightLightSearchedContent(ele);
}
}
})
//高亮顯示搜索內容
function hightLightSearchedContent(otext) {
$("#right").html(function() {
var reg = new RegExp(otext,"g");//g,表示全部替換。
return $(this).html().replace(reg,"<font color=\"red\">"+otext+"</font>");
});
}