ElasticSearch High Level REST API【2】搜索查詢


如下為一段帶有分頁的簡單搜索查詢示例

在search搜索中大部分的搜索條件添加都可通過設置SearchSourceBuilder來實現,然后將SearchSourceBuilder

RestHighLevelClient client = ElasticClient.getRestHighLevelClient();
SearchRequest searchRequest = new SearchRequest();
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
sourceBuilder.query(QueryBuilders.termQuery("user", "kimchy"));
sourceBuilder.from(0);
sourceBuilder.size(5);
sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS)); //設置一個可選的超時,控制允許搜索的時間
searchRequest.source(sourceBuilder);

try {
    SearchResponse search = client.search(searchRequest, RequestOptions.DEFAULT);
    Long total = search.getHits().getTotalHits(); //獲取匹配的總數量
    System.out.println("總記錄數:" + total);
    for (SearchHit hit : search.getHits().getHits()) {
              float score = hit.getScore(); //獲得分數,即匹配度 
          String source = hit.getSourceAsString();
          System.out.println(source);
    }

} catch (IOException e) {
    e.printStackTrace();
}

search查詢的返回值為SearchResponse,調用SearchResponse的getHits()方法會獲取SearchHits對象,然后再通過SearchHits的getHits()方法即返回一個SearchHit[]數組。

遍歷SearchHit[]數組獲取每一個對象,通過hit.getScore()可獲取分數,即搜索匹配度。通過hit.getSourceAsString()可得到對象的json字符串。

備注:在上述查詢中用到了termQuery查詢,ES還提供了matchQuery查詢,不同的查詢需求中需要選擇不同的查詢,在此需要了解這兩個查詢的區別:

  • termQuery : term為不使用分詞器查找,類似精確查找。
  • matchQuery : mactch為使用分詞器進行查找,會查詢到一些近似匹配的內容。

SearchHit使用匯總

要獲取返回的內容,需要獲得SearchHit,下面總結下SearchHit的一些使用:

SearchHits hits = searchResponse.getHits();
long totalHits = hits.getTotalHits(); //查詢命中總數
float maxScore = hits.getMaxScore(); //查詢命中的最高分數
//嵌套在SearchHits可以迭代獲取單個搜索結果中
SearchHit[] searchHits = hits.getHits();
for (SearchHit hit : searchHits) {
    //使用SearchHit做一些事情
}
//通過SearchHit還可以獲取 返回數據 的索引、類型、docId和得分等基本信息
String index = hit.getIndex(); 
String type = hit.getType();
String id = hit.getId();
float score = hit.getScore();
//hit還可以以Json字符串或Map的形式返回數據
String sourceAsString = hit.getSourceAsString();
Map<String, Object> sourceAsMap = hit.getSourceAsMap();
String documentTitle = (String) sourceAsMap.get("title");
List<Object> users = (List<Object>) sourceAsMap.get("user");
Map<String, Object> innerObject = (Map<String, Object>) sourceAsMap.get("innerObject");

指定排序

sourceBuilder.sort(new ScoreSortBuilder().order(SortOrder.DESC)); //按分數(即匹配度)排序
sourceBuilder.sort(new FieldSortBuilder("_uid").order(SortOrder.ASC)); //通過指定字段來排序

排序有兩種排序方式,第一通過ScoreSortBuilder實現按分數(即匹配度)排序

第二種方式通過指定字段來排序,如上圖所示通過“_uid”字段排序

關閉檢索

有時候我們只想要知道到底匹配了多少條具體,但不關系具體每條記錄的內容,這個時候我們可以選擇關閉檢索,不去查詢每天數據的內容,可通過如下方式實現:

sourceBuilder.fetchSource(false);

關閉檢索后,運行程序輸出如下

只返回了總記錄數,遍歷輸出每條數據均為 null

另外還可以通過sourceBuilder接受一個或多個數組,來控制要要返回哪些字段,排除哪些字段。具體實現如下,第一個數組參數為要接受的字段,第二個數組參數為要排除的內容:

String[] includeFields = new String[] {"title", "user", "innerObject.*"};
String[] excludeFields = new String[] {"_type"};
sourceBuilder.fetchSource(includeFields, excludeFields);

高亮顯示

通過向SearchSourceBuilder添加HighlightBuilder示例可添加高亮顯示功能

SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
HighlightBuilder highlightBuilder = new HighlightBuilder(); 
HighlightBuilder.Field highlightTitle = new HighlightBuilder.Field("title"); 
highlightTitle.highlighterType("unified"); //字段高亮顯示類型,默認用標簽包裹高亮字詞
highlightBuilder.field(highlightTitle);
searchSourceBuilder.highlighter(highlightBuilder);

以上只是在查詢中加入高亮顯示的功能,那么我們如何在查詢結果中獲取呢,通過SearchHit的getHighlightFields()方法獲取我們需要關鍵內容:

SearchHits hits = searchResponse.getHits();
for (SearchHit hit : hits.getHits()) {
    Map highlightFields = hit.getHighlightFields();
    HighlightField highlight = highlightFields.get("title"); 
    Text[] fragments = highlight.fragments();  
    String fragmentString = fragments[0].string();
}

 聚合操作

public void aggregation(){
       RestHighLevelClient client = elasticClient.getRestHighLevelClient();
       SearchRequest searchRequest = new SearchRequest();
       SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
       TermsAggregationBuilder aggregation = AggregationBuilders.terms("by_sex")
               .field("sex.keyword");   //若不加keyword,在text類型上進行聚合操作時會報錯
       aggregation.subAggregation(AggregationBuilders.avg("avg_age")
               .field("age"));  //avg_age 為子聚合名稱,名稱可隨意
       searchSourceBuilder.aggregation(aggregation);
       searchRequest.source(searchSourceBuilder);
       SearchResponse searchResponse = null;
       try {
           searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
       } catch (IOException e) {
           e.printStackTrace();
       }
       Aggregations aggregations = searchResponse.getAggregations();
       Terms byCompanyAggregation = aggregations.get("by_sex");
       Terms.Bucket elasticBucket = byCompanyAggregation.getBucketByKey("女性");
       Avg averageAge = elasticBucket.getAggregations().get("avg_age");
       double avg = averageAge.getValue();
       System.out.println("女性平均年齡:"+avg);
}

 


免責聲明!

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



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