zoukankan      html  css  js  c++  java
  • Elasticsearch实现复合查询,高亮结果等技巧

    一.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>.

    如果你觉得文章内容对你有用的话,不用忘记评论,点赞.

  • 相关阅读:
    【BZOJ 2124】【CodeVS 1283】等差子序列
    【BZOJ 1036】【ZJOI 2008】树的统计Count
    【BZOJ 1901】【ZJU 2112】Dynamic Rankings
    【BZOJ 3924】【ZJOI 2015】幻想乡战略游戏
    【BZOJ 4103】【THUSC 2015】异或运算
    【BZOJ 4513】【SDOI 2016】储能表
    【HDU 3622】Bomb Game
    【BZOJ 3166】【HEOI 2013】Alo
    【BZOJ 3530】【SDOI 2014】数数
    【BZOJ 4567】【SCOI 2016】背单词
  • 原文地址:https://www.cnblogs.com/haizhongdenta/p/11496473.html
Copyright © 2011-2022 走看看