目錄html
在上一篇 中主要介紹了 Document API,本節中講解 search API
java
Java High Level REST Client 支持下面的 Search API:編程
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
除了配置 index
和 type
外,還有一些其餘的可選參數異步
searchRequest.routing("routing"); // 設置 routing 參數 searchRequest.preference("_local"); // 配置搜索時偏心使用本地分片,默認是使用隨機分片
當索引一個文檔的時候,文檔會被存儲在一個主分片上。在存儲時通常都會有多個主分片。Elasticsearch 如何知道一個文檔應該放置在哪一個分片呢?這個過程是根據下面的這個公式來決定的:elasticsearch
shard = hash(routing) % number_of_primary_shards
routing
是一個可變值,默認是文檔的 _id
,也能夠設置成一個自定義的值number_of_primary_shards
是主分片數量全部的文檔 API 都接受一個叫作 routing
的路由參數,經過這個參數咱們能夠自定義文檔到分片的映射。一個自定義的路由參數能夠用來確保全部相關的文檔——例如全部屬於同一個用戶的文檔——都被存儲到同一個分片中。ide
對搜索行爲的配置能夠使用 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);
要實現聚合請求分兩步
AggregationBuilder
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);
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
對象,並在對象中包含查詢執行的細節和符合條件的文檔集合。
概括一下, SerchResponse
包含的信息以下
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 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
提供瞭如 index
, type
, docId
和每一個命中查詢的分數
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");
上面的 QueryBuilder
, SearchSourceBuilder
和 SearchRequest
之間都是嵌套關係,爲此我專門整理了一個關係圖,以便更清楚的確認它們之間的關係。感興趣的同窗可用此圖與前面的 API 進行對應,以加深理解。
本篇包含了 Java High level Rest Client 的 SearchAPI 部分,獲取高亮,聚合,分析的結果並無在本文涉及,須要的同窗可參考官方文檔,下篇會包含查詢構建,敬請期待~