欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Elasticsearch实现复合查询高亮结果功能

程序员文章站 2022-05-25 10:56:58
一.es的配置 实现es的全文检索功能的第一步,首先从与es进行连接开始,这里我使用的是es的5.x java api语法. public transportc...

一.es的配置

实现es的全文检索功能的第一步,首先从与es进行连接开始,这里我使用的是es的5.x java api语法.

public transportclient esclient() throws unknownhostexception{
    settings settings = settings.builder()
        .put("cluster.name", "my-application") //节点的名字
        .put("client.transport.sniff", true)
        .build();
    
    inetsockettransportaddress iaddress = new inetsockettransportaddress( //连接es的ip地址和端口号
        inetaddress.getbyname("127.0.0.1"),9300
        );
    
    //根据先前的配置生成client,后面的操作基本都是基于这个
    transportclient client = new prebuilttransportclient(settings)
        .addtransportaddress(iaddress);
    return client;
  }

二.功能的实现

以下是全文检索的核心代码,包括我遇到的错误以及解决,包括如何对高亮失效,高亮不全等的解决.

1.查询条件

 transportclient esclient = esclient();  //获取先前生成的client
    boolquerybuilder boolquery = querybuilders.boolquery(); //生成复合查询构造器
    
    boolquery.mustnot(
        querybuilders.matchquery("",) //字段必须不包含啥 
        );
    
    boolquery.should(
        querybuilders.matchquery(, )  //字段可以包含啥,相当于或者
        );

    boolquery.must(
        querybuilders.matchquery(,) //字段必须包含啥
        );

2.高亮条件

//配置标题高亮显示
    highlightbuilder highlightbuilder = new highlightbuilder(); //生成高亮查询器
    highlightbuilder.field(title);   //高亮查询字段
    highlightbuilder.field(content);  //高亮查询字段
    highlightbuilder.requirefieldmatch(false);   //如果要多个字段高亮,这项要为false
    highlightbuilder.pretags("<span style=\"color:red\">");  //高亮设置
    highlightbuilder.posttags("</span>");
    //下面这两项,如果你要高亮如文字内容等有很多字的字段,必须配置,不然会导致高亮不全,文章内容缺失等
    highlightbuilder.fragmentsize(800000); //最大高亮分片数
    highlightbuilder.numoffragments(0); //从第一个分片获取高亮片段

3.查询配置

// 根据字段进行排序,这里我根据时间进行倒排
fieldsortbuilder timesort = sortbuilders.fieldsort("time").order(sortorder.desc); 
     
    //查询请求生成
    searchrequestbuilder requestbuilder = esclient.preparesearch(indexname)//索引名字
            .settypes(indextype)   //索引类型
            .setquery(boolquery)   //配置查询条件
            .addsort(new scoresortbuilder())  //根据查询相关度进行排序
            .addsort(timesort)         //再根据时间进行排序
            .settrackscores(true)       //避免分页之后相关性乱了
            .highlighter(highlightbuilder)   //配置高亮
            .setfrom(from)         //设置分页
            .setsize();

4.获取查询结果对其高亮

   

 //获取查询结果
    searchresponse searchresponse = requestbuilder.get();
    list<map<string, object>> course = new arraylist<>(); 
    if(searchresponse.status() != reststatus.ok){
      return course;
    }
    for(searchhit hit:searchresponse.gethits()){
      //获取高亮字段
      map<string, highlightfield> highlightfields = hit.gethighlightfields();
      highlightfield titlefield = highlightfields.get("");
      highlightfield contentfield = highlightfields.get("");
      map<string, object> source = hit.getsource();
      //千万记得要记得判断是不是为空,不然你匹配的第一个结果没有高亮内容,那么就会报空指针异常,这个错误一开始真的搞了很久
      if(titlefield!=null){
        text[] fragments = titlefield.fragments(); 
        string name = "";
        for (text text : fragments) {
        name+=text;
        }
        source.put("", name);  //高亮字段替换掉原本的内容
        }
      course.add(source);
    }
    esclient.close();   //用完记得关闭
    return course;

三.结语

这样前端所获取结果的搜索内容将会被<span style="color:red;"></span>所包含,比如我前端是微信小程序,所以直接获取内容进行渲染的话,就是一堆字符串,所以用的是小程序的富文本标签<rich-text>.

总结

以上所述是小编给大家介绍的elasticsearch实现复合查询高亮结果功能,希望对大家有所帮助