Elasticsearch Java Rest Client API 整理總結 (二) —— SearchAPI

引言

上一篇 中主要介紹了 Document API,本節中講解 search APIjava

Search APIs

Java High Level REST Client 支持下面的 Search API:編程

Search API

Search Request

searchRequest 用來完成和搜索文檔,聚合,建議等相關的任何操做同時也提供了各類方式來完成對查詢結果的高亮操做。api

最基本的查詢操做以下dom

SearchRequest searchRequest = new SearchRequest(); 
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); 
searchSourceBuilder.query(QueryBuilders.matchAllQuery()); // 添加 match_all 查詢
searchRequest.source(searchSourceBuilder); // 將 SearchSourceBuilder  添加到 SeachRequest 中

可選參數

SearchRequest searchRequest = new SearchRequest("posts");  // 設置搜索的 index
searchRequest.types("doc");  // 設置搜索的 type

除了配置 indextype 外,還有一些其餘的可選參數異步

searchRequest.routing("routing"); // 設置 routing 參數
searchRequest.preference("_local");  // 配置搜索時偏心使用本地分片,默認是使用隨機分片

什麼是 routing 參數?

當索引一個文檔的時候,文檔會被存儲在一個主分片上。在存儲時通常都會有多個主分片。Elasticsearch 如何知道一個文檔應該放置在哪一個分片呢?這個過程是根據下面的這個公式來決定的:elasticsearch

shard = hash(routing) % number_of_primary_shards
  • routing 是一個可變值,默認是文檔的 _id ,也能夠設置成一個自定義的值
  • number_of_primary_shards 是主分片數量

全部的文檔 API 都接受一個叫作 routing 的路由參數,經過這個參數咱們能夠自定義文檔到分片的映射。一個自定義的路由參數能夠用來確保全部相關的文檔——例如全部屬於同一個用戶的文檔——都被存儲到同一個分片中。ide

使用 SearchSourceBuilder

對搜索行爲的配置能夠使用 SearchSourceBuilder 來完成,來看一個實例函數式編程

SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();  // 默認配置
sourceBuilder.query(QueryBuilders.termQuery("user", "kimchy")); // 設置搜索,能夠是任何類型的 QueryBuilder
sourceBuilder.from(0); // 起始 index
sourceBuilder.size(5); // 大小 size
sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS)); // 設置搜索的超時時間

設置完成後,就能夠添加到 SearchRequest 中。函數

SearchRequest searchRequest = new SearchRequest();
searchRequest.source(sourceBuilder);

構建查詢條件

查詢請求是經過使用 QueryBuilder 對象來完成的,而且支持 Query DSL

DSL (domain-specific language) 領域特定語言,是指專一於某個應用程序領域的計算機語言。

— 百度百科

能夠使用構造函數來建立 QueryBuilder

MatchQueryBuilder matchQueryBuilder = new MatchQueryBuilder("user", "kimchy");

QueryBuilder 建立後,就能夠調用方法來配置它的查詢選項:

matchQueryBuilder.fuzziness(Fuzziness.AUTO);  // 模糊查詢
matchQueryBuilder.prefixLength(3); // 前綴查詢的長度
matchQueryBuilder.maxExpansions(10); // max expansion 選項,用來控制模糊查詢

也能夠使用QueryBuilders 工具類來建立 QueryBuilder 對象。這個類提供了函數式編程風格的各類方法用來快速建立 QueryBuilder 對象。

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

fuzzy-matching 拼寫錯誤時的匹配:

好的全文檢索不該該是徹底相同的限定邏輯,相反,能夠擴大範圍來包括可能的匹配,從而根據相關性得分將更好的匹配放在前面。

例如,搜索 quick brown fox 時會匹配一個包含 fast brown foxes 的文檔

不論什麼方式建立的 QueryBuilder ,最後都須要添加到 `SearchSourceBuilder

searchSourceBuilder.query(matchQueryBuilder);

構建查詢 文檔中提供了一個豐富的查詢列表,裏面包含各類查詢對應的QueryBuilder 對象以及QueryBuilder helper 方法,你們能夠去參考。

關於構建查詢的內容會在下篇文章中講解,敬請期待。

指定排序

SearchSourceBuilder 容許添加一個或多個SortBuilder 實例。這裏包含 4 種特殊的實現, (Field-, Score-, GeoDistance-ScriptSortBuilder)

sourceBuilder.sort(new ScoreSortBuilder().order(SortOrder.DESC)); // 根據分數 _score 降序排列 (默認行爲)
sourceBuilder.sort(new FieldSortBuilder("_uid").order(SortOrder.ASC));  // 根據 id 降序排列

過濾數據源

默認狀況下,查詢請求會返回文檔的內容 _source ,固然咱們也能夠配置它。例如,禁止對 _source 的獲取

sourceBuilder.fetchSource(false);

也能夠使用通配符模式以更細的粒度包含或排除特定的字段:

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"); // title 字段高亮
highlightTitle.highlighterType("unified");  // 配置高亮類型
highlightBuilder.field(highlightTitle);  // 添加到 builder
HighlightBuilder.Field highlightUser = new HighlightBuilder.Field("user");
highlightBuilder.field(highlightUser);
searchSourceBuilder.highlighter(highlightBuilder);

聚合請求

要實現聚合請求分兩步

  1. 建立合適的 `AggregationBuilder
  2. 做爲參數配置在 `SearchSourceBuilder
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
TermsAggregationBuilder aggregation = AggregationBuilders.terms("by_company")
        .field("company.keyword");
aggregation.subAggregation(AggregationBuilders.avg("average_age")
        .field("age"));
searchSourceBuilder.aggregation(aggregation);

建議請求 Requesting Suggestions

SuggestionBuilder 實現類是由 SuggestBuilders 工廠類來建立的。

SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
SuggestionBuilder termSuggestionBuilder =
    SuggestBuilders.termSuggestion("user").text("kmichy"); 
SuggestBuilder suggestBuilder = new SuggestBuilder();
suggestBuilder.addSuggestion("suggest_user", termSuggestionBuilder); 
searchSourceBuilder.suggest(suggestBuilder);

對請求和聚合分析

分析 API 可用來對一個特定的查詢操做中的請求和聚合進行分析,此時要將SearchSourceBuilder 的 profile標誌位設置爲 true

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

只要 SearchRequest 執行完成,對應的 SearchResponse 響應中就會包含 分析結果

同步執行

同步執行是阻塞式的,只有結果返回後才能繼續執行。

SearchResponse searchResponse = client.search(searchRequest);

異步執行

異步執行使用的是 listener 對結果進行處理。

ActionListener<SearchResponse> listener = new ActionListener<SearchResponse>() {
    @Override
    public void onResponse(SearchResponse searchResponse) {
        // 查詢成功
    }

    @Override
    public void onFailure(Exception e) {
        // 查詢失敗
    }
};

查詢響應 SearchResponse

查詢執行完成後,會返回 SearchResponse 對象,並在對象中包含查詢執行的細節和符合條件的文檔集合。

概括一下, SerchResponse 包含的信息以下

  • 請求自己的信息,如 HTTP 狀態碼,執行時間,或者請求是否超時
RestStatus status = searchResponse.status(); // HTTP 狀態碼
TimeValue took = searchResponse.getTook(); // 查詢佔用的時間
Boolean terminatedEarly = searchResponse.isTerminatedEarly(); // 是否因爲 SearchSourceBuilder 中設置 terminateAfter 而過早終止
boolean timedOut = searchResponse.isTimedOut(); // 是否超時
  • 查詢影響的分片數量的統計信息,成功和失敗的分片
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 提供瞭如 indextypedocId 和每一個命中查詢的分數

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

並且,還能夠獲取到文檔的源數據,以 JSON-String 形式或者 key-value map 對的形式。在 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");

Search API 查詢關係

上面的 QueryBuilderSearchSourceBuilderSearchRequest 之間都是嵌套關係,爲此我專門整理了一個關係圖,以便更清楚的確認它們之間的關係。感興趣的同窗可用此圖與前面的 API 進行對應,以加深理解。

search API 關係圖

結語

本篇包含了 Java High level Rest Client 的 SearchAPI 部分,獲取高亮,聚合,分析的結果並無在本文涉及,須要的同窗可參考官方文檔,下篇會包含查詢構建,敬請期待~

系列文章列表

  1. Elasticsearch Java Rest Client API 整理總結 (一)——Document API
  2. Elasticsearch Java Rest Client API 整理總結 (二) —— SearchAPI
  3. Elasticsearch Java Rest Client API 整理總結 (三)——Building Queries
相關文章
相關標籤/搜索