Java使用IKAnalyzer实现多关键字查询
程序员文章站
2022-06-02 15:14:00
...
前端时间公司内部开发了一个小项目,方便运维人员在线上传查阅资料,其中搜索功能提出要实现 多关键字 结果高亮显示。
刚好想到之前项目使用过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>");
});
}
下一篇: SSM框架学习01——MyBatis