|
@@ -37,11 +37,8 @@ import org.elasticsearch.xcontent.ParseField;
|
|
|
import org.elasticsearch.xcontent.ToXContent;
|
|
|
import org.elasticsearch.xcontent.ToXContentFragment;
|
|
|
import org.elasticsearch.xcontent.XContentBuilder;
|
|
|
-import org.elasticsearch.xcontent.XContentParser;
|
|
|
-import org.elasticsearch.xcontent.XContentParser.Token;
|
|
|
|
|
|
import java.io.IOException;
|
|
|
-import java.util.ArrayList;
|
|
|
import java.util.Collections;
|
|
|
import java.util.Iterator;
|
|
|
import java.util.List;
|
|
@@ -53,7 +50,6 @@ import java.util.function.Predicate;
|
|
|
import java.util.function.Supplier;
|
|
|
|
|
|
import static org.elasticsearch.action.search.ShardSearchFailure.readShardSearchFailure;
|
|
|
-import static org.elasticsearch.common.xcontent.XContentParserUtils.ensureExpectedToken;
|
|
|
|
|
|
/**
|
|
|
* A response of a search request.
|
|
@@ -64,12 +60,12 @@ public class SearchResponse extends ActionResponse implements ChunkedToXContentO
|
|
|
// rather than empty string (RemoteClusterAware.LOCAL_CLUSTER_GROUP_KEY) we use internally
|
|
|
public static final String LOCAL_CLUSTER_NAME_REPRESENTATION = "(local)";
|
|
|
|
|
|
- private static final ParseField SCROLL_ID = new ParseField("_scroll_id");
|
|
|
- private static final ParseField POINT_IN_TIME_ID = new ParseField("pit_id");
|
|
|
- private static final ParseField TOOK = new ParseField("took");
|
|
|
- private static final ParseField TIMED_OUT = new ParseField("timed_out");
|
|
|
- private static final ParseField TERMINATED_EARLY = new ParseField("terminated_early");
|
|
|
- private static final ParseField NUM_REDUCE_PHASES = new ParseField("num_reduce_phases");
|
|
|
+ public static final ParseField SCROLL_ID = new ParseField("_scroll_id");
|
|
|
+ public static final ParseField POINT_IN_TIME_ID = new ParseField("pit_id");
|
|
|
+ public static final ParseField TOOK = new ParseField("took");
|
|
|
+ public static final ParseField TIMED_OUT = new ParseField("timed_out");
|
|
|
+ public static final ParseField TERMINATED_EARLY = new ParseField("terminated_early");
|
|
|
+ public static final ParseField NUM_REDUCE_PHASES = new ParseField("num_reduce_phases");
|
|
|
|
|
|
private final SearchHits hits;
|
|
|
private final InternalAggregations aggregations;
|
|
@@ -446,113 +442,6 @@ public class SearchResponse extends ActionResponse implements ChunkedToXContentO
|
|
|
return builder;
|
|
|
}
|
|
|
|
|
|
- public static SearchResponse fromXContent(XContentParser parser) throws IOException {
|
|
|
- ensureExpectedToken(Token.START_OBJECT, parser.nextToken(), parser);
|
|
|
- parser.nextToken();
|
|
|
- return innerFromXContent(parser);
|
|
|
- }
|
|
|
-
|
|
|
- public static SearchResponse innerFromXContent(XContentParser parser) throws IOException {
|
|
|
- ensureExpectedToken(Token.FIELD_NAME, parser.currentToken(), parser);
|
|
|
- String currentFieldName = parser.currentName();
|
|
|
- SearchHits hits = null;
|
|
|
- InternalAggregations aggs = null;
|
|
|
- Suggest suggest = null;
|
|
|
- SearchProfileResults profile = null;
|
|
|
- boolean timedOut = false;
|
|
|
- Boolean terminatedEarly = null;
|
|
|
- int numReducePhases = 1;
|
|
|
- long tookInMillis = -1;
|
|
|
- int successfulShards = -1;
|
|
|
- int totalShards = -1;
|
|
|
- int skippedShards = 0; // 0 for BWC
|
|
|
- String scrollId = null;
|
|
|
- String searchContextId = null;
|
|
|
- List<ShardSearchFailure> failures = new ArrayList<>();
|
|
|
- Clusters clusters = Clusters.EMPTY;
|
|
|
- for (Token token = parser.nextToken(); token != Token.END_OBJECT; token = parser.nextToken()) {
|
|
|
- if (token == Token.FIELD_NAME) {
|
|
|
- currentFieldName = parser.currentName();
|
|
|
- } else if (token.isValue()) {
|
|
|
- if (SCROLL_ID.match(currentFieldName, parser.getDeprecationHandler())) {
|
|
|
- scrollId = parser.text();
|
|
|
- } else if (POINT_IN_TIME_ID.match(currentFieldName, parser.getDeprecationHandler())) {
|
|
|
- searchContextId = parser.text();
|
|
|
- } else if (TOOK.match(currentFieldName, parser.getDeprecationHandler())) {
|
|
|
- tookInMillis = parser.longValue();
|
|
|
- } else if (TIMED_OUT.match(currentFieldName, parser.getDeprecationHandler())) {
|
|
|
- timedOut = parser.booleanValue();
|
|
|
- } else if (TERMINATED_EARLY.match(currentFieldName, parser.getDeprecationHandler())) {
|
|
|
- terminatedEarly = parser.booleanValue();
|
|
|
- } else if (NUM_REDUCE_PHASES.match(currentFieldName, parser.getDeprecationHandler())) {
|
|
|
- numReducePhases = parser.intValue();
|
|
|
- } else {
|
|
|
- parser.skipChildren();
|
|
|
- }
|
|
|
- } else if (token == Token.START_OBJECT) {
|
|
|
- if (SearchHits.Fields.HITS.equals(currentFieldName)) {
|
|
|
- hits = SearchHits.fromXContent(parser);
|
|
|
- } else if (InternalAggregations.AGGREGATIONS_FIELD.equals(currentFieldName)) {
|
|
|
- aggs = InternalAggregations.fromXContent(parser);
|
|
|
- } else if (Suggest.NAME.equals(currentFieldName)) {
|
|
|
- suggest = Suggest.fromXContent(parser);
|
|
|
- } else if (SearchProfileResults.PROFILE_FIELD.equals(currentFieldName)) {
|
|
|
- profile = SearchProfileResults.fromXContent(parser);
|
|
|
- } else if (RestActions._SHARDS_FIELD.match(currentFieldName, parser.getDeprecationHandler())) {
|
|
|
- while ((token = parser.nextToken()) != Token.END_OBJECT) {
|
|
|
- if (token == Token.FIELD_NAME) {
|
|
|
- currentFieldName = parser.currentName();
|
|
|
- } else if (token.isValue()) {
|
|
|
- if (RestActions.FAILED_FIELD.match(currentFieldName, parser.getDeprecationHandler())) {
|
|
|
- parser.intValue(); // we don't need it but need to consume it
|
|
|
- } else if (RestActions.SUCCESSFUL_FIELD.match(currentFieldName, parser.getDeprecationHandler())) {
|
|
|
- successfulShards = parser.intValue();
|
|
|
- } else if (RestActions.TOTAL_FIELD.match(currentFieldName, parser.getDeprecationHandler())) {
|
|
|
- totalShards = parser.intValue();
|
|
|
- } else if (RestActions.SKIPPED_FIELD.match(currentFieldName, parser.getDeprecationHandler())) {
|
|
|
- skippedShards = parser.intValue();
|
|
|
- } else {
|
|
|
- parser.skipChildren();
|
|
|
- }
|
|
|
- } else if (token == Token.START_ARRAY) {
|
|
|
- if (RestActions.FAILURES_FIELD.match(currentFieldName, parser.getDeprecationHandler())) {
|
|
|
- while (parser.nextToken() != Token.END_ARRAY) {
|
|
|
- failures.add(ShardSearchFailure.fromXContent(parser));
|
|
|
- }
|
|
|
- } else {
|
|
|
- parser.skipChildren();
|
|
|
- }
|
|
|
- } else {
|
|
|
- parser.skipChildren();
|
|
|
- }
|
|
|
- }
|
|
|
- } else if (Clusters._CLUSTERS_FIELD.match(currentFieldName, parser.getDeprecationHandler())) {
|
|
|
- clusters = Clusters.fromXContent(parser);
|
|
|
- } else {
|
|
|
- parser.skipChildren();
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- return new SearchResponse(
|
|
|
- hits,
|
|
|
- aggs,
|
|
|
- suggest,
|
|
|
- timedOut,
|
|
|
- terminatedEarly,
|
|
|
- profile,
|
|
|
- numReducePhases,
|
|
|
- scrollId,
|
|
|
- totalShards,
|
|
|
- successfulShards,
|
|
|
- skippedShards,
|
|
|
- tookInMillis,
|
|
|
- failures.toArray(ShardSearchFailure.EMPTY_ARRAY),
|
|
|
- clusters,
|
|
|
- searchContextId
|
|
|
- );
|
|
|
- }
|
|
|
-
|
|
|
@Override
|
|
|
public void writeTo(StreamOutput out) throws IOException {
|
|
|
assert hasReferences();
|
|
@@ -591,14 +480,14 @@ public class SearchResponse extends ActionResponse implements ChunkedToXContentO
|
|
|
|
|
|
public static final Clusters EMPTY = new Clusters(0, 0, 0);
|
|
|
|
|
|
- static final ParseField _CLUSTERS_FIELD = new ParseField("_clusters");
|
|
|
- static final ParseField TOTAL_FIELD = new ParseField("total");
|
|
|
- static final ParseField SUCCESSFUL_FIELD = new ParseField("successful");
|
|
|
- static final ParseField SKIPPED_FIELD = new ParseField("skipped");
|
|
|
- static final ParseField RUNNING_FIELD = new ParseField("running");
|
|
|
- static final ParseField PARTIAL_FIELD = new ParseField("partial");
|
|
|
- static final ParseField FAILED_FIELD = new ParseField("failed");
|
|
|
- static final ParseField DETAILS_FIELD = new ParseField("details");
|
|
|
+ public static final ParseField _CLUSTERS_FIELD = new ParseField("_clusters");
|
|
|
+ public static final ParseField TOTAL_FIELD = new ParseField("total");
|
|
|
+ public static final ParseField SUCCESSFUL_FIELD = new ParseField("successful");
|
|
|
+ public static final ParseField SKIPPED_FIELD = new ParseField("skipped");
|
|
|
+ public static final ParseField RUNNING_FIELD = new ParseField("running");
|
|
|
+ public static final ParseField PARTIAL_FIELD = new ParseField("partial");
|
|
|
+ public static final ParseField FAILED_FIELD = new ParseField("failed");
|
|
|
+ public static final ParseField DETAILS_FIELD = new ParseField("details");
|
|
|
|
|
|
private final int total;
|
|
|
private final int successful; // not used for minimize_roundtrips=true; dynamically determined from clusterInfo map
|
|
@@ -712,7 +601,7 @@ public class SearchResponse extends ActionResponse implements ChunkedToXContentO
|
|
|
+ failed;
|
|
|
}
|
|
|
|
|
|
- private Clusters(Map<String, Cluster> clusterInfoMap) {
|
|
|
+ public Clusters(Map<String, Cluster> clusterInfoMap) {
|
|
|
assert clusterInfoMap.size() > 0 : "this constructor should not be called with an empty Cluster info map";
|
|
|
this.total = clusterInfoMap.size();
|
|
|
this.clusterInfo = clusterInfoMap;
|
|
@@ -759,65 +648,6 @@ public class SearchResponse extends ActionResponse implements ChunkedToXContentO
|
|
|
return builder;
|
|
|
}
|
|
|
|
|
|
- public static Clusters fromXContent(XContentParser parser) throws IOException {
|
|
|
- XContentParser.Token token = parser.currentToken();
|
|
|
- ensureExpectedToken(XContentParser.Token.START_OBJECT, token, parser);
|
|
|
- int total = -1;
|
|
|
- int successful = -1;
|
|
|
- int skipped = -1;
|
|
|
- int running = 0; // 0 for BWC
|
|
|
- int partial = 0; // 0 for BWC
|
|
|
- int failed = 0; // 0 for BWC
|
|
|
- Map<String, Cluster> clusterInfoMap = ConcurrentCollections.newConcurrentMap();
|
|
|
- String currentFieldName = null;
|
|
|
- while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
|
|
|
- if (token == XContentParser.Token.FIELD_NAME) {
|
|
|
- currentFieldName = parser.currentName();
|
|
|
- } else if (token.isValue()) {
|
|
|
- if (Clusters.TOTAL_FIELD.match(currentFieldName, parser.getDeprecationHandler())) {
|
|
|
- total = parser.intValue();
|
|
|
- } else if (Clusters.SUCCESSFUL_FIELD.match(currentFieldName, parser.getDeprecationHandler())) {
|
|
|
- successful = parser.intValue();
|
|
|
- } else if (Clusters.SKIPPED_FIELD.match(currentFieldName, parser.getDeprecationHandler())) {
|
|
|
- skipped = parser.intValue();
|
|
|
- } else if (Clusters.RUNNING_FIELD.match(currentFieldName, parser.getDeprecationHandler())) {
|
|
|
- running = parser.intValue();
|
|
|
- } else if (Clusters.PARTIAL_FIELD.match(currentFieldName, parser.getDeprecationHandler())) {
|
|
|
- partial = parser.intValue();
|
|
|
- } else if (Clusters.FAILED_FIELD.match(currentFieldName, parser.getDeprecationHandler())) {
|
|
|
- failed = parser.intValue();
|
|
|
- } else {
|
|
|
- parser.skipChildren();
|
|
|
- }
|
|
|
- } else if (token == Token.START_OBJECT) {
|
|
|
- if (Clusters.DETAILS_FIELD.match(currentFieldName, parser.getDeprecationHandler())) {
|
|
|
- String currentDetailsFieldName = null;
|
|
|
- while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
|
|
|
- if (token == XContentParser.Token.FIELD_NAME) {
|
|
|
- currentDetailsFieldName = parser.currentName(); // cluster alias
|
|
|
- } else if (token == Token.START_OBJECT) {
|
|
|
- Cluster c = Cluster.fromXContent(currentDetailsFieldName, parser);
|
|
|
- clusterInfoMap.put(currentDetailsFieldName, c);
|
|
|
- } else {
|
|
|
- parser.skipChildren();
|
|
|
- }
|
|
|
- }
|
|
|
- } else {
|
|
|
- parser.skipChildren();
|
|
|
- }
|
|
|
- } else {
|
|
|
- parser.skipChildren();
|
|
|
- }
|
|
|
- }
|
|
|
- if (clusterInfoMap.isEmpty()) {
|
|
|
- assert running == 0 && partial == 0 && failed == 0
|
|
|
- : "Non cross-cluster should have counter for running, partial and failed equal to 0";
|
|
|
- return new Clusters(total, successful, skipped);
|
|
|
- } else {
|
|
|
- return new Clusters(clusterInfoMap);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
/**
|
|
|
* @return how many total clusters the search was requested to be executed on
|
|
|
*/
|
|
@@ -981,10 +811,10 @@ public class SearchResponse extends ActionResponse implements ChunkedToXContentO
|
|
|
* See the Clusters clusterInfo Map for details.
|
|
|
*/
|
|
|
public static class Cluster implements ToXContentFragment, Writeable {
|
|
|
- static final ParseField INDICES_FIELD = new ParseField("indices");
|
|
|
- static final ParseField STATUS_FIELD = new ParseField("status");
|
|
|
+ public static final ParseField INDICES_FIELD = new ParseField("indices");
|
|
|
+ public static final ParseField STATUS_FIELD = new ParseField("status");
|
|
|
|
|
|
- private static final boolean SKIP_UNAVAILABLE_DEFAULT = false;
|
|
|
+ public static final boolean SKIP_UNAVAILABLE_DEFAULT = false;
|
|
|
|
|
|
private final String clusterAlias;
|
|
|
private final String indexExpression; // original index expression from the user for this cluster
|
|
@@ -1242,96 +1072,6 @@ public class SearchResponse extends ActionResponse implements ChunkedToXContentO
|
|
|
return builder;
|
|
|
}
|
|
|
|
|
|
- public static Cluster fromXContent(String clusterAlias, XContentParser parser) throws IOException {
|
|
|
- XContentParser.Token token = parser.currentToken();
|
|
|
- ensureExpectedToken(XContentParser.Token.START_OBJECT, token, parser);
|
|
|
-
|
|
|
- String clusterName = clusterAlias;
|
|
|
- if (clusterAlias.equals(LOCAL_CLUSTER_NAME_REPRESENTATION)) {
|
|
|
- clusterName = "";
|
|
|
- }
|
|
|
- String indexExpression = null;
|
|
|
- String status = "running";
|
|
|
- boolean timedOut = false;
|
|
|
- long took = -1L;
|
|
|
- // these are all from the _shards section
|
|
|
- int totalShards = -1;
|
|
|
- int successfulShards = -1;
|
|
|
- int skippedShards = -1;
|
|
|
- int failedShards = -1;
|
|
|
- List<ShardSearchFailure> failures = new ArrayList<>();
|
|
|
-
|
|
|
- String currentFieldName = null;
|
|
|
- while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
|
|
|
- if (token == XContentParser.Token.FIELD_NAME) {
|
|
|
- currentFieldName = parser.currentName();
|
|
|
- } else if (token.isValue()) {
|
|
|
- if (Cluster.INDICES_FIELD.match(currentFieldName, parser.getDeprecationHandler())) {
|
|
|
- indexExpression = parser.text();
|
|
|
- } else if (Cluster.STATUS_FIELD.match(currentFieldName, parser.getDeprecationHandler())) {
|
|
|
- status = parser.text();
|
|
|
- } else if (TIMED_OUT.match(currentFieldName, parser.getDeprecationHandler())) {
|
|
|
- timedOut = parser.booleanValue();
|
|
|
- } else if (TOOK.match(currentFieldName, parser.getDeprecationHandler())) {
|
|
|
- took = parser.longValue();
|
|
|
- } else {
|
|
|
- parser.skipChildren();
|
|
|
- }
|
|
|
- } else if (RestActions._SHARDS_FIELD.match(currentFieldName, parser.getDeprecationHandler())) {
|
|
|
- while ((token = parser.nextToken()) != Token.END_OBJECT) {
|
|
|
- if (token == Token.FIELD_NAME) {
|
|
|
- currentFieldName = parser.currentName();
|
|
|
- } else if (token.isValue()) {
|
|
|
- if (RestActions.FAILED_FIELD.match(currentFieldName, parser.getDeprecationHandler())) {
|
|
|
- failedShards = parser.intValue();
|
|
|
- } else if (RestActions.SUCCESSFUL_FIELD.match(currentFieldName, parser.getDeprecationHandler())) {
|
|
|
- successfulShards = parser.intValue();
|
|
|
- } else if (RestActions.TOTAL_FIELD.match(currentFieldName, parser.getDeprecationHandler())) {
|
|
|
- totalShards = parser.intValue();
|
|
|
- } else if (RestActions.SKIPPED_FIELD.match(currentFieldName, parser.getDeprecationHandler())) {
|
|
|
- skippedShards = parser.intValue();
|
|
|
- } else {
|
|
|
- parser.skipChildren();
|
|
|
- }
|
|
|
- } else {
|
|
|
- parser.skipChildren();
|
|
|
- }
|
|
|
- }
|
|
|
- } else if (token == Token.START_ARRAY) {
|
|
|
- if (RestActions.FAILURES_FIELD.match(currentFieldName, parser.getDeprecationHandler())) {
|
|
|
- while (parser.nextToken() != Token.END_ARRAY) {
|
|
|
- failures.add(ShardSearchFailure.fromXContent(parser));
|
|
|
- }
|
|
|
- } else {
|
|
|
- parser.skipChildren();
|
|
|
- }
|
|
|
- } else {
|
|
|
- parser.skipChildren();
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- Integer totalShardsFinal = totalShards == -1 ? null : totalShards;
|
|
|
- Integer successfulShardsFinal = successfulShards == -1 ? null : successfulShards;
|
|
|
- Integer skippedShardsFinal = skippedShards == -1 ? null : skippedShards;
|
|
|
- Integer failedShardsFinal = failedShards == -1 ? null : failedShards;
|
|
|
- TimeValue tookTimeValue = took == -1L ? null : new TimeValue(took);
|
|
|
- boolean skipUnavailable = SKIP_UNAVAILABLE_DEFAULT; // skipUnavailable is not exposed to XContent, so just use default
|
|
|
-
|
|
|
- return new Cluster(
|
|
|
- clusterName,
|
|
|
- indexExpression,
|
|
|
- skipUnavailable,
|
|
|
- SearchResponse.Cluster.Status.valueOf(status.toUpperCase(Locale.ROOT)),
|
|
|
- totalShardsFinal,
|
|
|
- successfulShardsFinal,
|
|
|
- skippedShardsFinal,
|
|
|
- failedShardsFinal,
|
|
|
- failures,
|
|
|
- tookTimeValue,
|
|
|
- timedOut
|
|
|
- );
|
|
|
- }
|
|
|
-
|
|
|
public String getClusterAlias() {
|
|
|
return clusterAlias;
|
|
|
}
|