Java與ES
本節主要內容是使用ES客戶端Java High Level REST Client操作ES(推薦使用該客戶端)。
Java High Level REST Client
是ElasticSearch
官方目前推薦使用的,適用於6.x以上的版本,要求JDK在1.8以上,可以很好的在大版本中進行兼容,並且該架包自身也包含Java Low Level REST Client
中的方法,可以應對一些特需的情況進行特殊的處理, 它對於一些常用的方法封裝Restful風格,可以直接對應操作名調用使用即可,支持同步和異步(Async)調用。
Spring Boot集成ES
POM依賴
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>7.6.2</version>
</dependency>
<properties>
<!--需要覆蓋默認的ES版本配置,與本地引入的ES版本保持一致-->
<elasticsearch.version>7.6.2</elasticsearch.version>
</properties>
集成代碼
package com.wangqiang.config;
import org.apache.http.HttpHost;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class ElasticSearchClientConfig {
@Bean
// 硬編碼的值可以設置到配置文件,通過@Value讀取
public RestHighLevelClient restHighLevelClient(){
RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(new HttpHost("127.0.0.1", 9200, "http")));
return client;
}
}
索引操作和文檔基本操作
import java.io.IOException;
import java.util.ArrayList;
import java.util.concurrent.TimeUnit;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.support.master.AcknowledgedResponse;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.CreateIndexRequest;
import org.elasticsearch.client.indices.CreateIndexResponse;
import org.elasticsearch.client.indices.GetIndexRequest;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.TermQueryBuilder;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.FetchSourceContext;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.test.context.SpringBootTest;
import com.alibaba.fastjson.JSON;
/**
* es7.6.x 高級客戶端測試 API
*/
@SpringBootTest
public class ElasticsearchJdApplicationTests {
// 面向對象來操作
@Autowired
@Qualifier("restHighLevelClient")
private RestHighLevelClient client;
// 測試索引的創建 Request PUT kuang_index
@Test
void testCreateIndex() throws IOException {
// 1、創建索引請求
CreateIndexRequest request = new CreateIndexRequest("kuang_index");
// 2、客戶端執行請求 IndicesClient,請求后獲得響應
CreateIndexResponse createIndexResponse = client.indices().create(request, RequestOptions.DEFAULT);
System.out.println(createIndexResponse);
}
// 測試獲取索引,判斷其是否存在
@Test
void testExistIndex() throws IOException {
GetIndexRequest request = new GetIndexRequest("kuang_index2");
boolean exists = client.indices().exists(request, RequestOptions.DEFAULT);
System.out.println(exists);
}
// 測試刪除索引
@Test
void testDeleteIndex() throws IOException {
DeleteIndexRequest request = new DeleteIndexRequest("kuang_index");
// 刪除
AcknowledgedResponse delete = client.indices().delete(request, RequestOptions.DEFAULT);
System.out.println(delete.isAcknowledged());
}
// 測試添加文檔
@Test
void testAddDocument() throws IOException {
// 創建對象
User user = new User("狂神說", 3);
// 創建請求
IndexRequest request = new IndexRequest("kuang_index");
// 規則 put /kuang_index/_doc/1
request.id("1");
request.timeout(TimeValue.timeValueSeconds(1));
request.timeout("1s");
// 將我們的數據放入請求 json
request.source(JSON.toJSONString(user), XContentType.JSON);
// 客戶端發送請求 , 獲取響應的結果
IndexResponse indexResponse = client.index(request, RequestOptions.DEFAULT);
System.out.println(indexResponse.toString()); //
System.out.println(indexResponse.status()); // 對應我們命令返回的狀態CREATED
}
// 獲取文檔,判斷是否存在 get /index/doc/1
@Test
void testIsExists() throws IOException {
GetRequest getRequest = new GetRequest("kuang_index", "1");
// 不獲取返回的 _source 的上下文了
getRequest.fetchSourceContext(new FetchSourceContext(false));
getRequest.storedFields("_none_");
boolean exists = client.exists(getRequest, RequestOptions.DEFAULT);
System.out.println(exists);
}
// 獲得文檔的信息
@Test
void testGetDocument() throws IOException {
GetRequest getRequest = new GetRequest("kuang_index", "1");
GetResponse getResponse = client.get(getRequest, RequestOptions.DEFAULT);
System.out.println(getResponse.getSourceAsString()); // 打印文檔的內容
System.out.println(getResponse); // 返回的全部內容和命令式一樣的
}
// 更新文檔的信息
@Test
void testUpdateRequest() throws IOException {
UpdateRequest updateRequest = new UpdateRequest("kuang_index", "1");
updateRequest.timeout("1s");
User user = new User("狂神說Java", 18);
updateRequest.doc(JSON.toJSONString(user), XContentType.JSON);
UpdateResponse updateResponse = client.update(updateRequest, RequestOptions.DEFAULT);
System.out.println(updateResponse.status());
}
// 刪除文檔記錄
@Test
void testDeleteRequest() throws IOException {
DeleteRequest request = new DeleteRequest("kuang_index", "1");
request.timeout("1s");
DeleteResponse deleteResponse = client.delete(request, RequestOptions.DEFAULT);
System.out.println(deleteResponse.status());
}
// 特殊的,真的項目一般都會批量插入數據!
@Test
void testBulkRequest() throws IOException {
BulkRequest bulkRequest = new BulkRequest();
bulkRequest.timeout("10s");
ArrayList<User> userList = new ArrayList<>();
userList.add(new User("kuangshen1", 3));
userList.add(new User("kuangshen2", 3));
userList.add(new User("kuangshen3", 3));
userList.add(new User("qinjiang1", 3));
userList.add(new User("qinjiang1", 3));
userList.add(new User("qinjiang1", 3));
// 批處理請求
for (int i = 0; i < userList.size(); i++) {
// 批量更新和批量刪除,就在這里修改對應的請求就可以了
bulkRequest.add(new IndexRequest("kuang_index").id("" + (i + 1))
.source(JSON.toJSONString(userList.get(i)), XContentType.JSON));
}
BulkResponse bulkResponse = client.bulk(bulkRequest, RequestOptions.DEFAULT);
System.out.println(bulkResponse.hasFailures()); // 是否失敗,返回 false 代表 成功!
}
// 查詢
// SearchRequest 搜索請求
// SearchSourceBuilder 條件構造
// HighlightBuilder 構建高亮
// TermQueryBuilder 精確查詢
// MatchAllQueryBuilder
// xxx QueryBuilder 對應我們剛才看到的命令!
@Test
void testSearch() throws IOException {
SearchRequest searchRequest = new SearchRequest("kuang_index");
// 構建搜索條件
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
sourceBuilder.highlighter();
// 查詢條件,我們可以使用 QueryBuilders 工具來實現
// QueryBuilders.termQuery 精確
// QueryBuilders.matchAllQuery() 匹配所有
TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("name", "qinjiang1");
// MatchAllQueryBuilder matchAllQueryBuilder =
QueryBuilders.matchAllQuery();
sourceBuilder.query(termQueryBuilder);
sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));
searchRequest.source(sourceBuilder);
SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
System.out.println(JSON.toJSONString(searchResponse.getHits()));
System.out.println("=================================");
for (SearchHit documentFields : searchResponse.getHits().getHits()) {
System.out.println(documentFields.getSourceAsMap());
}
}
}
查詢接口
一個基本的查詢構造
1、創建SearchRequest,不帶參數,表示查詢所有索引
2、添加大部分查詢參數到 SearchSourceBuilder,接收QueryBuilders構建的查詢參數
3、添加 match_all 查詢到 SearchSourceBuilder
4、添加 SearchSourceBuilder 到 SearchRequest
SearchRequest searchRequest = new SearchRequest();
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
searchSourceBuilder.query(QueryBuilders.matchAllQuery());
searchRequest.source(searchSourceBuilder);
SearchRequest 有一些可選參數
// 指定查詢“posts”索引
SearchRequest searchRequest = new SearchRequest("posts");
// 設置路由
searchRequest.routing("routing");
// IndicesOptions 設置如何解析未知的索引及通配符表達式如何擴展
searchRequest.indicesOptions(IndicesOptions.lenientExpandOpen());
// 設置偏好參數,如設置搜索本地分片的偏好,默認是在分片中隨機檢索
searchRequest.preference("_local");
使用SearchSourceBuilder
控制搜索行為的大多數選項都可以在 SearchSourceBuilder 上設置,該構建器或多或少包含與Rest API 的search request中的選項等價的設置。下面是一些通用設置選項:
// 使用默認參數創建 SearchSourceBuilder
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
// 可以設置任何類型的QueryBuilder查詢參數
sourceBuilder.query(QueryBuilders.termQuery("user", "kimchy"));
// 設置查詢的起始位置,默認是0
sourceBuilder.from(0);
// 設置查詢結果的頁大小,默認是10
sourceBuilder.size(5);
// 設置當前查詢的超時時間
sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));
設置完上面 的SearchSourceBuilder ,只需要將其設置到 SearchRequest中即可。
SearchRequest searchRequest = new SearchRequest();
searchRequest.indices("posts");
searchRequest.source(sourceBuilder);
構建查詢參數QueryBuilder
使用QueryBuilder構建查詢參數,QueryBuilder包括所有Elasticsearch’s Query DSL支持的類型。
可以使用QueryBuilde構造器創建一個QueryBuilder:
// 構建一個全文檢索Match Query, 查詢匹配kimchy的user字段
MatchQueryBuilder matchQueryBuilder = new MatchQueryBuilder("user", "kimchy");
// 可以針對創建的QueryBuilder對象設置查詢參數
// 開啟模糊查詢
matchQueryBuilder.fuzziness(Fuzziness.AUTO);
// 設置查詢前綴長度
matchQueryBuilder.prefixLength(3);
// 設置模糊查詢最大擴展
matchQueryBuilder.maxExpansions(10);
可以使用工具類QueryBuilders,采用流式編程的形式構建QueryBuilder
QueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("user", "kimchy")
.fuzziness(Fuzziness.AUTO)
.prefixLength(3)
.maxExpansions(10);
不管使用上述兩種方式的哪種來創建QueryBuilder, QueryBuilder都必須按如下方式設置到SearchSourceBuilder.
searchSourceBuilder.query(matchQueryBuilder);
Building Queries 頁給出了所有的查詢QueryBuilder及輔助類QueryBuilders的表達方式。
指定排序
SearchSourceBuilder允許增加一或多個排序參數SortBuilder,有四個具體實現FieldSortBuilder, ScoreSortBuilder, GeoDistanceSortBuilder 和 ScriptSortBuilder。
// 默認排序。根據_score倒序
sourceBuilder.sort(new ScoreSortBuilder().order(SortOrder.DESC));
// 根據_id升序
sourceBuilder.sort(new FieldSortBuilder("id").order(SortOrder.ASC));
使用Source字段過濾
默認情況下,查詢請求會返回_source字段的全部內容,但是該行為可以被覆寫,比如,你可以完全關掉該字段的索引(不推薦,該行為,原因參考上面的鏈接)
sourceBuilder.fetchSource(false);
該方法fetchSource也可以接收組通配模式來以更細粒度地方式控制哪些字段被包含或者被排除。
String[] includeFields = new String[] {"title", "innerObject.*"};
String[] excludeFields = new String[] {"user"};
sourceBuilder.fetchSource(includeFields, excludeFields);
搜索結果突出(Highlighting)
通過向 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);
// 設置HighlightBuilder到SearchSourceBuilder
searchSourceBuilder.highlighter(highlightBuilder);
詳細的選項可以參考Rest API的文檔。
高亮的文本片斷可以在下面的 later be retrieved SearchResponse中獲取。
實際樣例
// 獲取數據實現高亮功能
public List<Map<String, Object>> searchPageHighlightBuilder(String keyword, int pageNo, int pageSize)
throws IOException {
if (pageNo <= 1) {
pageNo = 1;
}
keyword = URLDecoder.decode(keyword, "UTF-8");
// 條件搜索
SearchRequest searchRequest = new SearchRequest("jd_goods");
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
// 分頁
searchSourceBuilder.from(pageNo);
searchSourceBuilder.size(pageSize);
// 精准匹配
TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("title", keyword);
searchSourceBuilder.query(termQueryBuilder);
searchSourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));
// 高亮
HighlightBuilder highlightBuilder = new HighlightBuilder();
highlightBuilder.field("title");
highlightBuilder.requireFieldMatch(true);// 多個高亮顯示
highlightBuilder.preTags("<span style='color:red'>");
highlightBuilder.postTags("</span>");
searchSourceBuilder.highlighter(highlightBuilder);
// 執行搜索
searchRequest.source(searchSourceBuilder);
SearchResponse search = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
// 解析結果
ArrayList<Map<String, Object>> list = new ArrayList<>();
for (SearchHit documentFields : search.getHits().getHits()) {
// 解析高亮的字段
Map<String, HighlightField> highlightFields = documentFields.getHighlightFields();
HighlightField title = highlightFields.get("title");
Map<String, Object> sourceAsMap = documentFields.getSourceAsMap();
if (title != null) {
Text[] fragments = title.fragments();
String n_title = "";
for (Text text : fragments) {
n_title += text;
}
sourceAsMap.put("title", n_title);
}
list.add(sourceAsMap);
}
return list;
}
請求聚合(Requesting Aggregations)
通過構建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);
Building Aggregations頁給出了聚合對象AggregationBuilder及輔助類AggregationBuilders的對應關系及使用方式。
后面會介紹如何從SearchResponse中獲取聚合結果。 access aggregations
請求建議Requesting Suggestions
在查詢請求中可以設置請求Suggestions,通過使用SuggestBuilders輔助類,或者SuggestionBuilder構造器,將其設置到SuggestBuilder,最后將SuggestBuilder設置SearchSourceBuilder中。
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
// 為字段user和文本kmichy創建 TermSuggestionBuilder
SuggestionBuilder termSuggestionBuilder = SuggestBuilders.termSuggestion("user").text("kmichy");
SuggestBuilder suggestBuilder = new SuggestBuilder();
// 添加TermSuggestionBuilder到suggestBuilder中,並命名為suggest_user
suggestBuilder.addSuggestion("suggest_user", termSuggestionBuilder);
searchSourceBuilder.suggest(suggestBuilder);
后面會介紹如何從SearchResponse中檢索建議retrieve suggestions
Profiling Queries和aggregations
Profile API可以配置某個具體的查詢或聚合請求的執行過程。如果想使用該功能,需要將SearchSourceBuilder的開關打開。
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
searchSourceBuilder.profile(true);
SearchRequest執行后,SearchResponse會包含配置的執行信息。contain the profiling results
執行查詢
同步查詢執行Synchronous execution
下面是同步查詢執行方式,客戶端會等待SearchResponse的結果返回后,才繼續執行后面的代碼。
SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
high-level REST client 的同步請求可能拋出IOException。
異步查詢執行Asynchronous execution
SearchRequest也可以以異步方式執行。用戶需要指定listenert到異步請求中,告訴異步請求如何處理響應或潛在的錯誤。
client.searchAsync(searchRequest, RequestOptions.DEFAULT, listener);
searchRequest執行完成后會調用ActionListener
異步方式不會阻塞,當該異步調用結果后,ActionListener會被調用,如果執行成功,則onResponse會被調用,如果失敗,則onFailure被調用。一個典型的search listener如下:
ActionListener<SearchResponse> listener = new ActionListener<SearchResponse>() {
@Override
public void onResponse(SearchResponse searchResponse) {
}
@Override
public void onFailure(Exception e) {
}
};
SearchResponse
SearchResponse提供了查詢執行的細節以及返回的文檔結果。首先,SearchResponse包括當前查詢的執行細節,比如HTTP響應碼、執行時間、或者是否超時等:
RestStatus status = searchResponse.status();
TimeValue took = searchResponse.getTook();
Boolean terminatedEarly = searchResponse.isTerminatedEarly();
boolean timedOut = searchResponse.isTimedOut();
其次,SearchResponse提供了查詢涉及的分片統計信息,包含執行成功和執行失敗的分片。執行的錯誤信息ShardSearchFailures可以通過如下方式迭代處理:
int totalShards = searchResponse.getTotalShards();
int successfulShards = searchResponse.getSuccessfulShards();
int failedShards = searchResponse.getFailedShards();
for (ShardSearchFailure failure : searchResponse.getShardFailures()) {
// failures should be handled here
}
檢索結果Retrieving SearchHits
為了獲取到結果中的文檔信息,我們首先要獲取response中的搜索結果集SearchHits:
SearchHits hits = searchResponse.getHits();
SearchHits提供了所有命中結果的全局信息,包括命中的總數或者最大的score:
TotalHits totalHits = hits.getTotalHits();
// the total number of hits, must be interpreted in the context of totalHits.relation
long numHits = totalHits.value;
// whether the number of hits is accurate (EQUAL_TO) or a lower bound of the total (GREATER_THAN_OR_EQUAL_TO)
TotalHits.Relation relation = totalHits.relation;
float maxScore = hits.getMaxScore();
SearchHits中的單個結果集可以迭代獲取:
SearchHit[] searchHits = hits.getHits();
for (SearchHit hit : searchHits) {
// do something with the SearchHit
}
單個結果集SearchHit包含了一些基本信息:索引、文檔ID、每個命中結果的score
String index = hit.getIndex();
String id = hit.getId();
float score = hit.getScore();
此外,SearchHit可以以JSON或MAP形式返回文檔的source信息。在Map中,普通的字段以字段名作為key,值為字段值。多值字段是以對象列表形式返回,嵌套對象,則以另一個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");
獲取突出內容(Retrieving Highlighting)
如果設置了highlighting的請求,則返回的SearchHit中可以獲取到突出的text文本片斷。
SearchHits hits = searchResponse.getHits();
for (SearchHit hit : hits.getHits()) {
Map<String, HighlightField> highlightFields = hit.getHighlightFields();
// Get the highlighting for the title field
HighlightField highlight = highlightFields.get("title");
// Get one or many fragments containing the highlighted field content
Text[] fragments = highlight.fragments();
String fragmentString = fragments[0].string();
}
獲取聚合結果(Retrieving Aggregations)
首先從SearchResponse中獲取聚合樹aggregation tree的根,聚合對象Aggregations,然后可以根據名稱獲取聚合對象aggregation。
Aggregations aggregations = searchResponse.getAggregations();
// Get the by_company terms aggregation
Terms byCompanyAggregation = aggregations.get("by_company");
// Get the buckets that is keyed with Elastic
Bucket elasticBucket = byCompanyAggregation.getBucketByKey("Elastic");
// Get the average_age sub-aggregation from that bucket
Avg averageAge = elasticBucket.getAggregations().get("average_age");
double avg = averageAge.getValue();
注意,如果使用名稱獲取Aggregations,需要指定aggregation 接口為請求里設置的aggregation 類型,否則會拋出ClassCastException 異常。
// This will throw an exception because "by_company" is a terms aggregation but we try to retrieve it as a range aggregation
Range range = aggregations.get("by_company");
也可以以map的形式獲取aggregations,key是aggregation名稱。這種情況下,aggregation 接口需要顯式的強轉。
Map<String, Aggregation> aggregationMap = aggregations.getAsMap();
Terms companyAggregation = (Terms) aggregationMap.get("by_company");
也有方式將所有top level aggregations以列表形式返回:
List<Aggregation> aggregationList = aggregations.asList();
最后,可以迭代所有aggregations:
for (Aggregation agg : aggregations) {
String type = agg.getType();
if (type.equals(TermsAggregationBuilder.NAME)) {
Bucket elasticBucket = ((Terms) agg).getBucketByKey("Elastic");
long numberOfDocs = elasticBucket.getDocCount();
}
}
獲取建議結果(Retrieving Suggestions)
為了從SearchResponse中獲取suggestions,可以使用Suggest對象作為入口。
// Use the Suggest class to access suggestions
Suggest suggest = searchResponse.getSuggest();
// Suggestions can be retrieved by name. You need to assign them to the correct type of Suggestion class (here TermSuggestion), otherwise a ClassCastException is thrown
TermSuggestion termSuggestion = suggest.getSuggestion("suggest_user");
// Iterate over the suggestion entries
for (TermSuggestion.Entry entry : termSuggestion.getEntries()) {
// Iterate over the options in one entry
for (TermSuggestion.Entry.Option option : entry) {
String suggestText = option.getText().string();
}
}
獲取配置結果(Retrieving Profiling Results)
可以使用SearchResponse的getProfileResults()方法獲取。返回結果為每個分片包裝一個Map,值為ProfileShardResult對象。key是能唯一標識分片的信息。
// Retrieve the Map of ProfileShardResult from the SearchResponse
Map<String, ProfileShardResult> profilingResults = searchResponse.getProfileResults();
// Profiling results can be retrieved by shard’s key if the key is known, otherwise it might be simpler to iterate over all the profiling results
for (Map.Entry<String, ProfileShardResult> profilingResult : profilingResults.entrySet()) {
// Retrieve the key that identifies which shard the ProfileShardResult belongs to
String key = profilingResult.getKey();
// Retrieve the ProfileShardResult for the given shard
ProfileShardResult profileShardResult = profilingResult.getValue();
}
ProfileShardResult包含一個或多個profile 結果:
// Retrieve the list of QueryProfileShardResult
List<QueryProfileShardResult> queryProfileShardResults =
profileShardResult.getQueryProfileResults();
// Iterate over each QueryProfileShardResult
for (QueryProfileShardResult queryProfileResult : queryProfileShardResults) {
}
每個QueryProfileShardResult 中可以獲取ProfileResult對象列表:
// Iterate over the profile results
for (ProfileResult profileResult : queryProfileResult.getQueryResults()) {
// Retrieve the name of the Lucene query
String queryName = profileResult.getQueryName();
// Retrieve the time in millis spent executing the Lucene query
long queryTimeInMillis = profileResult.getTime();
// Retrieve the profile results for the sub-queries (if any)
List<ProfileResult> profiledChildren = profileResult.getProfiledChildren();
}
QueryProfileShardResult也可以獲取Lucene collectors的信息:
// Retrieve the profiling result of the Lucene collector
CollectorResult collectorResult = queryProfileResult.getCollectorResult();
// Retrieve the name of the Lucene collector
String collectorName = collectorResult.getName();
// Retrieve the time in millis spent executing the Lucene collector
Long collectorTimeInMillis = collectorResult.getTime();
// Retrieve the profile results for the sub-collectors (if any)
List<CollectorResult> profiledChildren = collectorResult.getProfiledChildren();
QueryProfileShardResult可以獲取詳細的aggregations tree執行信息:
// Retrieve the AggregationProfileShardResult
AggregationProfileShardResult aggsProfileResults =
profileShardResult.getAggregationProfileResults();
// Iterate over the aggregation profile results
for (ProfileResult profileResult : aggsProfileResults.getProfileResults()) {
// Retrieve the type of the aggregation (corresponds to Java class used to execute the aggregation)
String aggName = profileResult.getQueryName();
// Retrieve the time in millis spent executing the Lucene collector
long aggTimeInMillis = profileResult.getTime();
// Retrieve the profile results for the sub-aggregations (if any)
List<ProfileResult> profiledChildren = profileResult.getProfiledChildren();
}