Java使用IKAnalyzer实现多关键字查询

前端时间公司内部开发了一个小项目,方便运维人员在线上传查阅资料,其中搜索功能提出要实现 多关键字 结果高亮显示。

刚好想到之前项目使用过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);
                    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>");
        });
    }

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值