Ver código fonte

[Docs] Add profile section to the Search API documentation (#25880)

Tanguy Leroux 8 anos atrás
pai
commit
90ebaaa9a8

+ 80 - 5
client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/SearchDocumentationIT.java

@@ -23,6 +23,7 @@ import org.elasticsearch.action.ActionListener;
 import org.elasticsearch.action.bulk.BulkRequest;
 import org.elasticsearch.action.bulk.BulkResponse;
 import org.elasticsearch.action.index.IndexRequest;
+import org.elasticsearch.action.index.IndexResponse;
 import org.elasticsearch.action.search.ClearScrollRequest;
 import org.elasticsearch.action.search.ClearScrollResponse;
 import org.elasticsearch.action.search.SearchRequest;
@@ -52,6 +53,11 @@ import org.elasticsearch.search.aggregations.metrics.avg.Avg;
 import org.elasticsearch.search.builder.SearchSourceBuilder;
 import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
 import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
+import org.elasticsearch.search.profile.ProfileResult;
+import org.elasticsearch.search.profile.ProfileShardResult;
+import org.elasticsearch.search.profile.aggregation.AggregationProfileShardResult;
+import org.elasticsearch.search.profile.query.CollectorResult;
+import org.elasticsearch.search.profile.query.QueryProfileShardResult;
 import org.elasticsearch.search.sort.FieldSortBuilder;
 import org.elasticsearch.search.sort.ScoreSortBuilder;
 import org.elasticsearch.search.sort.SortOrder;
@@ -70,6 +76,7 @@ import java.util.concurrent.TimeUnit;
 
 import static org.elasticsearch.index.query.QueryBuilders.matchQuery;
 import static org.hamcrest.Matchers.containsString;
+import static org.hamcrest.Matchers.equalTo;
 import static org.hamcrest.Matchers.greaterThan;
 
 /**
@@ -105,7 +112,7 @@ public class SearchDocumentationIT extends ESRestHighLevelClientTestCase {
                             Arrays.asList("kimchy", "tanguy"), "innerObject", Collections.singletonMap("key", "value")));
             request.setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE);
             BulkResponse bulkResponse = client.bulk(request);
-            assertSame(bulkResponse.status(), RestStatus.OK);
+            assertSame(RestStatus.OK, bulkResponse.status());
             assertFalse(bulkResponse.hasFailures());
         }
         {
@@ -244,7 +251,7 @@ public class SearchDocumentationIT extends ESRestHighLevelClientTestCase {
                     .source(XContentType.JSON, "company", "Elastic", "age", 40));
             request.setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE);
             BulkResponse bulkResponse = client.bulk(request);
-            assertSame(bulkResponse.status(), RestStatus.OK);
+            assertSame(RestStatus.OK, bulkResponse.status());
             assertFalse(bulkResponse.hasFailures());
         }
         {
@@ -317,7 +324,7 @@ public class SearchDocumentationIT extends ESRestHighLevelClientTestCase {
             request.add(new IndexRequest("posts", "doc", "4").source(XContentType.JSON, "user", "cbuescher"));
             request.setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE);
             BulkResponse bulkResponse = client.bulk(request);
-            assertSame(bulkResponse.status(), RestStatus.OK);
+            assertSame(RestStatus.OK, bulkResponse.status());
             assertFalse(bulkResponse.hasFailures());
         }
         {
@@ -364,7 +371,7 @@ public class SearchDocumentationIT extends ESRestHighLevelClientTestCase {
                             Arrays.asList("kimchy", "tanguy"), "innerObject", Collections.singletonMap("key", "value")));
             request.setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE);
             BulkResponse bulkResponse = client.bulk(request);
-            assertSame(bulkResponse.status(), RestStatus.OK);
+            assertSame(RestStatus.OK, bulkResponse.status());
             assertFalse(bulkResponse.hasFailures());
         }
         {
@@ -412,6 +419,74 @@ public class SearchDocumentationIT extends ESRestHighLevelClientTestCase {
         }
     }
 
+    public void testSearchRequestProfiling() throws IOException {
+        RestHighLevelClient client = highLevelClient();
+        {
+            IndexRequest request = new IndexRequest("posts", "doc", "1")
+                    .source(XContentType.JSON, "tags", "elasticsearch", "comments", 123);
+            request.setRefreshPolicy(WriteRequest.RefreshPolicy.WAIT_UNTIL);
+            IndexResponse indexResponse = client.index(request);
+            assertSame(RestStatus.CREATED, indexResponse.status());
+        }
+        {
+            SearchRequest searchRequest = new SearchRequest();
+            // tag::search-request-profiling
+            SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
+            searchSourceBuilder.profile(true);
+            // end::search-request-profiling
+            searchSourceBuilder.query(QueryBuilders.termQuery("tags", "elasticsearch"));
+            searchSourceBuilder.aggregation(AggregationBuilders.histogram("by_comments").field("comments").interval(100));
+            searchRequest.source(searchSourceBuilder);
+
+            SearchResponse searchResponse = client.search(searchRequest);
+            // tag::search-request-profiling-get
+            Map<String, ProfileShardResult> profilingResults = searchResponse.getProfileResults(); // <1>
+            for (Map.Entry<String, ProfileShardResult> profilingResult : profilingResults.entrySet()) {  // <2>
+                String key = profilingResult.getKey(); // <3>
+                ProfileShardResult profileShardResult = profilingResult.getValue(); // <4>
+            }
+            // end::search-request-profiling-get
+
+            ProfileShardResult profileShardResult = profilingResults.values().iterator().next();
+            assertNotNull(profileShardResult);
+
+            // tag::search-request-profiling-queries
+            List<QueryProfileShardResult> queryProfileShardResults = profileShardResult.getQueryProfileResults(); // <1>
+            for (QueryProfileShardResult queryProfileResult : queryProfileShardResults) { // <2>
+
+            }
+            // end::search-request-profiling-queries
+            assertThat(queryProfileShardResults.size(), equalTo(1));
+
+            for (QueryProfileShardResult queryProfileResult : queryProfileShardResults) {
+                // tag::search-request-profiling-queries-results
+                for (ProfileResult profileResult : queryProfileResult.getQueryResults()) { // <1>
+                    String queryName = profileResult.getQueryName(); // <2>
+                    long queryTimeInMillis = profileResult.getTime(); // <3>
+                    List<ProfileResult> profiledChildren = profileResult.getProfiledChildren(); // <4>
+                }
+                // end::search-request-profiling-queries-results
+
+                // tag::search-request-profiling-queries-collectors
+                CollectorResult collectorResult = queryProfileResult.getCollectorResult();  // <1>
+                String collectorName = collectorResult.getName();  // <2>
+                Long collectorTimeInMillis = collectorResult.getTime(); // <3>
+                List<CollectorResult> profiledChildren = collectorResult.getProfiledChildren(); // <4>
+                // end::search-request-profiling-queries-collectors
+            }
+
+            // tag::search-request-profiling-aggs
+            AggregationProfileShardResult aggsProfileResults = profileShardResult.getAggregationProfileResults(); // <1>
+            for (ProfileResult profileResult : aggsProfileResults.getProfileResults()) { // <2>
+                String aggName = profileResult.getQueryName(); // <3>
+                long aggTimeInMillis = profileResult.getTime(); // <4>
+                List<ProfileResult> profiledChildren = profileResult.getProfiledChildren(); // <5>
+            }
+            // end::search-request-profiling-aggs
+            assertThat(aggsProfileResults.getProfileResults().size(), equalTo(1));
+        }
+    }
+
     public void testScroll() throws IOException {
         RestHighLevelClient client = highLevelClient();
         {
@@ -424,7 +499,7 @@ public class SearchDocumentationIT extends ESRestHighLevelClientTestCase {
                     .source(XContentType.JSON, "title", "The Future of Federated Search in Elasticsearch"));
             request.setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE);
             BulkResponse bulkResponse = client.bulk(request);
-            assertSame(bulkResponse.status(), RestStatus.OK);
+            assertSame(RestStatus.OK, bulkResponse.status());
             assertFalse(bulkResponse.hasFailures());
         }
         {

+ 87 - 0
docs/java-rest/high-level/apis/search.asciidoc

@@ -163,6 +163,19 @@ the text `kmichy`
 We will later see how to <<java-rest-high-retrieve-suggestions,retrieve suggestions>> from the
 `SearchResponse`.
 
+===== Profiling Queries and Aggregations
+
+The {ref}/search-profile.html[Profile API] can be used to profile the execution of queries and aggregations for
+a specific search request. in order to use it, the profile flag must be set to true on the `SearchSourceBuilder`:
+
+["source","java",subs="attributes,callouts,macros"]
+--------------------------------------------------
+include-tagged::{doc-tests}/SearchDocumentationIT.java[search-request-profiling]
+--------------------------------------------------
+
+Once the `SearchRequest` is executed the corresponding `SearchResponse` will
+<<java-rest-high-retrieve-profile-results,contain the profiling results>>.
+
 [[java-rest-high-document-search-sync]]
 ==== Synchronous Execution
 
@@ -339,3 +352,77 @@ include-tagged::{doc-tests}/SearchDocumentationIT.java[search-request-suggestion
 type of Suggestion class (here `TermSuggestion`), otherwise a `ClassCastException` is thrown
 <3> Iterate over the suggestion entries
 <4> Iterate over the options in one entry
+
+[[java-rest-high-retrieve-profile-results]]
+===== Retrieving Profiling Results
+
+Profiling results are retrieved from a `SearchResponse` using the `getProfileResults()` method. This
+ method returns a `Map` containing a `ProfileShardResult` object for every shard involved in the
+ `SearchRequest` execution. `ProfileShardResult` are stored in the `Map` using a key that uniquely
+ identifies the shard the profile result corresponds to.
+
+Here is a sample code that shows how to iterate over all the profiling results of every shard:
+
+["source","java",subs="attributes,callouts,macros"]
+--------------------------------------------------
+include-tagged::{doc-tests}/SearchDocumentationIT.java[search-request-profiling-get]
+--------------------------------------------------
+<1> Retrieve the `Map` of `ProfileShardResult` from the `SearchResponse`
+<2> 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
+<3> Retrieve the key that identifies which shard the `ProfileShardResult` belongs to
+<4> Retrieve the `ProfileShardResult` for the given shard
+
+The `ProfileShardResult` object itself contains one or more query profile results, one for each query
+executed against the underlying Lucene index:
+
+["source","java",subs="attributes,callouts,macros"]
+--------------------------------------------------
+include-tagged::{doc-tests}/SearchDocumentationIT.java[search-request-profiling-queries]
+--------------------------------------------------
+<1> Retrieve the list of `QueryProfileShardResult`
+<2> Iterate over each `QueryProfileShardResult`
+
+Each `QueryProfileShardResult` gives access to the detailed query tree execution, returned as a list of
+`ProfileResult` objects:
+
+["source","java",subs="attributes,callouts,macros"]
+--------------------------------------------------
+include-tagged::{doc-tests}/SearchDocumentationIT.java[search-request-profiling-queries-results]
+--------------------------------------------------
+<1> Iterate over the profile results
+<2> Retrieve the name of the Lucene query
+<3> Retrieve the time in millis spent executing the Lucene query
+<4> Retrieve the profile results for the sub-queries (if any)
+
+The Rest API documentation contains more information about {ref}/_profiling_queries.html[Profiling Queries] with
+a description of the {ref}/_profiling_queries.html#_literal_query_literal_section[query profiling information]
+
+The `QueryProfileShardResult` also gives access to the profiling information for the Lucene collectors:
+
+["source","java",subs="attributes,callouts,macros"]
+--------------------------------------------------
+include-tagged::{doc-tests}/SearchDocumentationIT.java[search-request-profiling-queries-collectors]
+--------------------------------------------------
+<1> Retrieve the profiling result of the Lucene collector
+<2> Retrieve the name of the Lucene collector
+<3> Retrieve the time in millis spent executing the Lucene collector
+<4> Retrieve the profile results for the sub-collectors (if any)
+
+The Rest API documentation contains more information about profiling information
+{ref}/_profiling_queries.html#_literal_collectors_literal_section[for Lucene collectors].
+
+In a very similar manner to the query tree execution, the `QueryProfileShardResult` objects gives access
+to the detailed aggregations tree execution:
+
+["source","java",subs="attributes,callouts,macros"]
+--------------------------------------------------
+include-tagged::{doc-tests}/SearchDocumentationIT.java[search-request-profiling-aggs]
+--------------------------------------------------
+<1> Retrieve the `AggregationProfileShardResult`
+<2> Iterate over the aggregation profile results
+<3> Retrieve the type of the aggregation (corresponds to Java class used to execute the aggregation)
+<4> Retrieve the time in millis spent executing the Lucene collector
+<5> Retrieve the profile results for the sub-aggregations (if any)
+
+The Rest API documentation contains more information about {ref}/_profiling_aggregations.html[Profiling Aggregations]