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

如果你覺得文章內容對你有用的話,不用忘記評論,點贊.


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM