Elasticsearch Java High Level REST Client(Search API)

Search API

搜索請求

SearchRequest用於與搜索文檔、聚合、suggestions相關的任何操做,還提供了在結果文檔上請求高亮的方法。編程

在最基本的表單中,咱們能夠向請求添加查詢:segmentfault

SearchRequest searchRequest = new SearchRequest(); 
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); 
searchSourceBuilder.query(QueryBuilders.matchAllQuery()); 
searchRequest.source(searchSourceBuilder);
  • 建立SeachRequest,沒有參數,這將針對全部索引運行。
  • 大多數搜索參數都添加到SearchSourceBuilder中,它爲搜索請求body中的全部內容提供了setter。
  • match_all查詢添加到SearchSourceBuilder
  • SearchSourceBuilder添加到SeachRequest

可選參數

咱們先來看一下SearchRequest的一些可選參數:數組

SearchRequest searchRequest = new SearchRequest("posts");
searchRequest.types("doc");
  • 將請求限制爲一個索引。
  • 將請求限制爲一個類型。

還有一些其餘有趣的可選參數:異步

searchRequest.routing("routing");
  • 設置路由參數。
searchRequest.indicesOptions(IndicesOptions.lenientExpandOpen());
  • 設置IndicesOptions控制如何解析不可用的索引以及如何擴展通配符表達式。
searchRequest.preference("_local");
  • 使用首選項參數,例如執行搜索以優先選擇本地碎片,默認是隨機的跨碎片。

使用SearchSourceBuilder

控制搜索行爲的大多數選項均可以在SearchSourceBuilder上設置,它包含或多或少與Rest API的搜索請求body中等效的選項。ide

如下是一些常見選項的幾個示例:函數

SearchSourceBuilder sourceBuilder = new SearchSourceBuilder(); 
sourceBuilder.query(QueryBuilders.termQuery("user", "kimchy")); 
sourceBuilder.from(0); 
sourceBuilder.size(5); 
sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));
  • 使用默認選項建立SearchSourceBuilder
  • 設置查詢,能夠是任何類型的QueryBuilder
  • 設置肯定結果要從哪一個索引開始搜索的from選項,默認爲0
  • 設置肯定搜索命中返回的數的size選項,默認爲10
  • 設置一個可選的超時,控制容許搜索的時間。

在此以後,只需將SearchSourceBuilder添加到SearchRequestpost

SearchRequest searchRequest = new SearchRequest();
searchRequest.indices("posts");
searchRequest.source(sourceBuilder);

構建查詢

使用QueryBuilder對象建立搜索查詢,QueryBuilder存在對於Elasticsearch的查詢DSL支持的每種搜索查詢類型。性能

可使用其構造函數建立QueryBuilderfetch

MatchQueryBuilder matchQueryBuilder = new MatchQueryBuilder("user", "kimchy");
  • 建立一個在字段「user」上匹配文本「kimchy」的全文匹配查詢

建立後,QueryBuilder對象提供了配置其建立的搜索查詢選項的方法:ui

matchQueryBuilder.fuzziness(Fuzziness.AUTO); 
matchQueryBuilder.prefixLength(3); 
matchQueryBuilder.maxExpansions(10);
  • 在匹配查詢上啓用模糊匹配。
  • 在匹配查詢上設置前綴長度選項。
  • 設置最大擴展選項以控制查詢的模糊過程。

也可使用QueryBuilders實用程序類建立QueryBuilder對象,此類提供了可用於使用流暢的編程樣式建立QueryBuilder對象的輔助方法:

QueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("user", "kimchy")
                                                .fuzziness(Fuzziness.AUTO)
                                                .prefixLength(3)
                                                .maxExpansions(10);

不管用於建立它的方法是什麼,都必須將QueryBuilder對象添加到SearchSourceBuilder,以下所示:

searchSourceBuilder.query(matchQueryBuilder);

構建查詢頁面提供了全部可用的搜索查詢的列表及其相應的QueryBuilder對象和QueryBuilders輔助方法。

指定排序

SearchSourceBuilder容許添加一個或多個SortBuilder實例,有四種特殊的實現(Field-,Score-,GeoDistance-和ScriptSortBuilder)。

sourceBuilder.sort(new ScoreSortBuilder().order(SortOrder.DESC)); 
sourceBuilder.sort(new FieldSortBuilder("_uid").order(SortOrder.ASC));
  • _score降序排序(默認值)。
  • 也能夠按_id字段進行升序排序。

源過濾

默認狀況下,搜索請求會返回文檔_source的內容,但與Rest API中的內容同樣,你能夠覆蓋此行爲,例如,你能夠徹底關閉_source檢索:

sourceBuilder.fetchSource(false);

該方法還接受一個或多個通配符模式的數組,以控制以更精細的方式包含或排除哪些字段:

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

請求高亮

經過在SearchSourceBuilder上設置HighlightBuilder,能夠實現高亮搜索結果,經過將一個或多個HighlightBuilder.Field實例添加到HighlightBuilder,能夠爲每一個字段定義不一樣的高亮行爲。

SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
HighlightBuilder highlightBuilder = new HighlightBuilder(); 
HighlightBuilder.Field highlightTitle =
        new HighlightBuilder.Field("title"); 
highlightTitle.highlighterType("unified");  
highlightBuilder.field(highlightTitle);  
HighlightBuilder.Field highlightUser = new HighlightBuilder.Field("user");
highlightBuilder.field(highlightUser);
searchSourceBuilder.highlighter(highlightBuilder);
  • 建立一個新的HighlightBuilder
  • title字段建立字段高光色。
  • 設置字段高光色類型。
  • 將字段高光色添加到高亮構建器。

Rest API文檔中有許多選項須要詳細說明,Rest API參數(例如pre_tags)一般由具備類似名稱的setter更改而來(例如#preTags(String ...))。

稍後能夠從SearchResponse中檢索高亮的文本片斷。

請求聚合

能夠經過先建立適當的AggregationBuilder而後在SearchSourceBuilder上設置聚合來將聚合添加到搜索中,在如下示例中,咱們在公司名稱上建立terms聚合 ,使用子聚合在公司員工平均年齡上:

SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
TermsAggregationBuilder aggregation = AggregationBuilders.terms("by_company")
        .field("company.keyword");
aggregation.subAggregation(AggregationBuilders.avg("average_age")
        .field("age"));
searchSourceBuilder.aggregation(aggregation);

構建聚合頁面提供了全部可用的聚合的列表及其對應的AggregationBuilder對象和AggregationBuilders輔助方法。

稍後咱們將看到如何訪問SearchResponse中的聚合。

請求Suggestion

要向搜索請求添加建議,請使用從SuggestBuilders工廠類中可輕鬆訪問的SuggestionBuilder的實現之一,Suggestion構建器須要添加到頂級SuggestBuilder,它自己能夠在SearchSourceBuilder上設置。

SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
SuggestionBuilder termSuggestionBuilder =
    SuggestBuilders.termSuggestion("user").text("kmichy"); 
SuggestBuilder suggestBuilder = new SuggestBuilder();
suggestBuilder.addSuggestion("suggest_user", termSuggestionBuilder); 
searchSourceBuilder.suggest(suggestBuilder);
  • user字段和文本kmichy建立一個新的TermSuggestionBuilder
  • 添加suggestion構建器並將其命名爲suggest_user

咱們稍後將看到如何從SearchResponse中檢索suggestion。

分析查詢和聚合

分析API可用於分析特定搜索請求的查詢和聚合的執行狀況,爲了使用它,必須在SearchSourceBuilder上將profile標誌設置爲true

SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
searchSourceBuilder.profile(true);

執行SearchRequest後,相應的SearchResponse將包含分析結果。

同步執行

如下列方式執行SearchRequest時,客戶端在繼續執行代碼以前等待返回SearchResponse

SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);

異步執行

執行SearchRequest也能夠以異步方式完成,以便客戶端能夠直接返回,用戶須要經過將請求和監聽器傳遞給異步搜索方法來指定響應或潛在的故障如何處理:

client.searchAsync(searchRequest, RequestOptions.DEFAULT, listener);
  • 要執行的SearchRequest和執行完成時要使用的ActionListener

異步方法不會阻塞而且當即返回,完成後,若是執行成功完成則使用onResponse方法回調ActionListener,若是失敗則使用onFailure方法。

SearchResponse的典型監聽器以下所示:

ActionListener<SearchResponse> listener = new ActionListener<SearchResponse>() {
    @Override
    public void onResponse(SearchResponse searchResponse) {
        
    }

    @Override
    public void onFailure(Exception e) {
        
    }
};
  • onResponse:執行成功完成時調用。
  • onFailure:在整個SearchRequest失敗時調用。

SearchResponse

經過執行搜索返回的SearchResponse提供有關搜索執行自己以及對返回文檔的訪問的詳細信息,首先,有關於請求執行自己的有用信息,例如HTTP狀態碼,執行時間或請求是提早終止仍是超時:

RestStatus status = searchResponse.status();
TimeValue took = searchResponse.getTook();
Boolean terminatedEarly = searchResponse.isTerminatedEarly();
boolean timedOut = searchResponse.isTimedOut();

其次,響應還經過提供有關搜索影響的碎片總數以及成功與不成功碎片的統計信息的碎片級別執行的信息,能夠經過在ShardSearchFailures上迭代數組來處理可能的失敗,以下例所示:

int totalShards = searchResponse.getTotalShards();
int successfulShards = searchResponse.getSuccessfulShards();
int failedShards = searchResponse.getFailedShards();
for (ShardSearchFailure failure : searchResponse.getShardFailures()) {
    // failures should be handled here
}

檢索SearchHits

要訪問返回的文檔,咱們須要先獲取響應中包含的SearchHits

SearchHits hits = searchResponse.getHits();

SearchHits提供有關全部匹配的全局信息,例如總命中數或最高分數:

long totalHits = hits.getTotalHits();
float maxScore = hits.getMaxScore();

嵌套在SearchHits中的是能夠迭代的單個搜索結果:

SearchHit[] searchHits = hits.getHits();
for (SearchHit hit : searchHits) {
    // do something with the SearchHit
}

SearchHit提供對每一個搜索命中的索引、類型、docId和分數等基本信息的訪問:

String index = hit.getIndex();
String type = hit.getType();
String id = hit.getId();
float score = hit.getScore();

此外,它還容許你以簡單的JSON-String或鍵/值對映射的形式返回文檔源,在此映射中,常規字段由字段名稱鍵控幷包含字段值,多值字段做爲對象列表返回,嵌套對象做爲另外一個鍵/值映射返回,這些案例須要相應地進行投射:

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");

檢索高亮

若是須要,能夠從結果中的每一個SearchHit檢索高亮的文本片斷,命中對象提供對HighlightField實例的字段名稱映射的訪問,每一個實例包含一個或多個高亮的文本片斷:

SearchHits hits = searchResponse.getHits();
for (SearchHit hit : hits.getHits()) {
    Map<String, HighlightField> highlightFields = hit.getHighlightFields();
    HighlightField highlight = highlightFields.get("title"); 
    Text[] fragments = highlight.fragments();  
    String fragmentString = fragments[0].string();
}
  • 獲取title字段的高亮。
  • 獲取包含高亮的字段內容的一個或多個片斷。

檢索聚合

能夠從SearchResponse檢索聚合,先獲取聚合樹的根,Aggregations對象,而後按名稱獲取聚合。

Aggregations aggregations = searchResponse.getAggregations();
Terms byCompanyAggregation = aggregations.get("by_company"); 
Bucket elasticBucket = byCompanyAggregation.getBucketByKey("Elastic"); 
Avg averageAge = elasticBucket.getAggregations().get("average_age"); 
double avg = averageAge.getValue();
  • 獲取by_companyterms聚合。
  • 獲取使用Elastic鍵入的桶。
  • 從該桶中獲取average_age子聚合。

請注意,若是按名稱訪問聚合,則須要根據所請求的聚合類型指定聚合接口,不然將引起ClassCastException

Range range = aggregations.get("by_company");
  • 這將引起異常,由於「by_company」是一個terms聚合,但咱們嘗試將其做爲range聚合進行檢索。

還能夠將全部聚合做爲由聚合名稱鍵入的映射進行訪問,在這種狀況下,須要顯式地進行到正確聚合接口的轉換:

Map<String, Aggregation> aggregationMap = aggregations.getAsMap();
Terms companyAggregation = (Terms) aggregationMap.get("by_company");

還有一些getter將全部頂級聚合做爲列表返回:

List<Aggregation> aggregationList = aggregations.asList();

最後但並不是最不重要的是,你能夠迭代全部聚合,而後例如決定如何根據類型進一步處理它們:

for (Aggregation agg : aggregations) {
    String type = agg.getType();
    if (type.equals(TermsAggregationBuilder.NAME)) {
        Bucket elasticBucket = ((Terms) agg).getBucketByKey("Elastic");
        long numberOfDocs = elasticBucket.getDocCount();
    }
}

檢索suggestions

要從SearchResponse獲取suggestions,請使用Suggest對象做爲入口點,而後檢索嵌套的suggestion對象:

Suggest suggest = searchResponse.getSuggest(); 
TermSuggestion termSuggestion = suggest.getSuggestion("suggest_user"); 
for (TermSuggestion.Entry entry : termSuggestion.getEntries()) { 
    for (TermSuggestion.Entry.Option option : entry) { 
        String suggestText = option.getText().string();
    }
}
  • 使用Suggest類訪問suggestions。
  • 能夠經過名稱檢索suggestions,你須要將它們分配給正確類型的Suggestion類(此處爲TermSuggestion),不然拋出ClassCastException
  • 迭代suggestion條目。
  • 在一個條目中迭代選項。

檢索性能分析結果

使用getProfileResults()方法從SearchResponse檢索分析結果,此方法返回包含SearchSquest執行中涉及的每一個碎片的ProfileShardResult對象的MapProfileShardResult使用惟一標識分析結果對應的碎片的鍵存儲在Map中。

下面是一個示例代碼,顯示如何迭代每一個碎片的全部分析結果:

Map<String, ProfileShardResult> profilingResults =
        searchResponse.getProfileResults(); 
for (Map.Entry<String, ProfileShardResult> profilingResult : profilingResults.entrySet()) { 
    String key = profilingResult.getKey(); 
    ProfileShardResult profileShardResult = profilingResult.getValue(); 
}
  • SearchResponse中檢索ProfileShardResultMap
  • 若是鍵已知,則能夠經過碎片的鍵檢索分析結果,不然迭代全部分析結果可能更簡單。
  • 檢索標識ProfileShardResult屬於哪一個碎片的鍵。
  • 檢索給定碎片的ProfileShardResult

ProfileShardResult對象自己包含一個或多個查詢分析結果,每一個查詢針對基礎Lucene索引執行:

List<QueryProfileShardResult> queryProfileShardResults =
        profileShardResult.getQueryProfileResults(); 
for (QueryProfileShardResult queryProfileResult : queryProfileShardResults) { 

}
  • 檢索QueryProfileShardResult的列表。
  • 迭代每一個QueryProfileShardResult

每一個QueryProfileShardResult都提供對詳細查詢樹執行的訪問,做爲ProfileResult對象列表返回:

for (ProfileResult profileResult : queryProfileResult.getQueryResults()) { 
    String queryName = profileResult.getQueryName(); 
    long queryTimeInMillis = profileResult.getTime(); 
    List<ProfileResult> profiledChildren = profileResult.getProfiledChildren(); 
}
  • 迭代分析結果。
  • 檢索Lucene查詢的名稱。
  • 檢索執行Lucene查詢所花費的時間。
  • 檢索子查詢的分析結果(若是有)。

Rest API文檔包含有關分析查詢的更多信息以及查詢分析信息的說明。

QueryProfileShardResult還能夠訪問Lucene收集器的分析信息:

CollectorResult collectorResult = queryProfileResult.getCollectorResult();  
String collectorName = collectorResult.getName();  
Long collectorTimeInMillis = collectorResult.getTime(); 
List<CollectorResult> profiledChildren = collectorResult.getProfiledChildren();
  • 檢索Lucene收集器的分析結果。
  • 檢索Lucene收集器的名稱。
  • 檢索執行Lucene收集器所花費的時間。
  • 檢索子收集器的分析結果(若是有)。

Rest API文檔包含有關Lucene收集器的分析信息的更多信息。

以與查詢樹執行很是相似的方式,QueryProfileShardResult對象提供對詳細聚合樹執行的訪問:

AggregationProfileShardResult aggsProfileResults =
        profileShardResult.getAggregationProfileResults(); 
for (ProfileResult profileResult : aggsProfileResults.getProfileResults()) { 
    String aggName = profileResult.getQueryName(); 
    long aggTimeInMillis = profileResult.getTime(); 
    List<ProfileResult> profiledChildren = profileResult.getProfiledChildren(); 
}
  • 檢索AggregationProfileShardResult
  • 迭代聚合分析結果。
  • 檢索聚合的類型(對應於用於執行聚合的Java類)。
  • 檢索執行Lucene收集器所花費的時間。
  • 檢索子聚合的分析結果(若是有)。

Rest API文檔包含有關分析聚合的更多信息。

相關文章
相關標籤/搜索