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

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

  • 相关阅读:
    ActiveMQ简单介绍+简单实例
    分布式开放消息系统(RocketMQ)的原理与实践
    RocketMQ实战(一)
    十分钟入门RocketMQ
    android Lib
    JDK1.8 Lambda
    JDK1.8聚合操作
    JNI
    Gradle插件
    Weex命令
  • 原文地址:https://www.cnblogs.com/haizhongdenta/p/11496473.html
Copyright © 2020-2023  润新知