diff --git a/server/src/main/java/org/opensearch/action/search/AbstractSearchAsyncAction.java b/server/src/main/java/org/opensearch/action/search/AbstractSearchAsyncAction.java index 332a0c17b26fb..c8405d087a482 100644 --- a/server/src/main/java/org/opensearch/action/search/AbstractSearchAsyncAction.java +++ b/server/src/main/java/org/opensearch/action/search/AbstractSearchAsyncAction.java @@ -182,6 +182,9 @@ abstract class AbstractSearchAsyncAction exten this.indexRoutings = indexRoutings; this.results = resultConsumer; this.clusters = clusters; + if (timeProvider.isPhaseTookEnabled()) { + searchListenersList.add(timeProvider); + } if (!CollectionUtils.isEmpty(searchListenersList)) { this.searchListenersList = searchListenersList; this.searchRequestOperationsListener = new SearchRequestOperationsListener.CompositeListener(this.searchListenersList, logger); @@ -333,6 +336,7 @@ public final void start() { 0, 0, buildTookInMillis(), + timeProvider.getPhaseTook(), ShardSearchFailure.EMPTY_ARRAY, clusters, null @@ -791,6 +795,7 @@ protected final SearchResponse buildSearchResponse( successfulOps.get(), skippedOps.get(), buildTookInMillis(), + timeProvider.getPhaseTook(), failures, clusters, searchContextId diff --git a/server/src/main/java/org/opensearch/action/search/SearchRequest.java b/server/src/main/java/org/opensearch/action/search/SearchRequest.java index 762022460ebdb..c9d5819e586e7 100644 --- a/server/src/main/java/org/opensearch/action/search/SearchRequest.java +++ b/server/src/main/java/org/opensearch/action/search/SearchRequest.java @@ -117,6 +117,8 @@ public class SearchRequest extends ActionRequest implements IndicesRequest.Repla private String pipeline; + private Boolean phaseTookQueryParamEnabled = null; + public SearchRequest() { this.localClusterAlias = null; this.absoluteStartMillis = DEFAULT_ABSOLUTE_START_MILLIS; @@ -209,6 +211,7 @@ private SearchRequest( this.absoluteStartMillis = absoluteStartMillis; this.finalReduce = finalReduce; this.cancelAfterTimeInterval = searchRequest.cancelAfterTimeInterval; + this.phaseTookQueryParamEnabled = searchRequest.phaseTookQueryParamEnabled; } /** @@ -253,6 +256,7 @@ public SearchRequest(StreamInput in) throws IOException { if (in.getVersion().onOrAfter(Version.V_2_7_0)) { pipeline = in.readOptionalString(); } + phaseTookQueryParamEnabled = in.readOptionalBoolean(); } @Override @@ -284,6 +288,7 @@ public void writeTo(StreamOutput out) throws IOException { if (out.getVersion().onOrAfter(Version.V_2_7_0)) { out.writeOptionalString(pipeline); } + out.writeOptionalBoolean(phaseTookQueryParamEnabled); } @Override @@ -615,6 +620,33 @@ public void setPreFilterShardSize(int preFilterShardSize) { this.preFilterShardSize = preFilterShardSize; } + enum ParamValue { + TRUE, + FALSE, + UNSET + } + + /** + * Returns value of user-provided phase_took query parameter for this search request. + * Defaults to false. + */ + public ParamValue isPhaseTookQueryParamEnabled() { + if (phaseTookQueryParamEnabled == null) { + return ParamValue.UNSET; + } else if (phaseTookQueryParamEnabled == true) { + return ParamValue.TRUE; + } else { + return ParamValue.FALSE; + } + } + + /** + * Sets value of phase_took query param if provided by user. Defaults to null. + */ + public void setPhaseTookQueryParamEnabled(boolean phaseTookQueryParamEnabled) { + this.phaseTookQueryParamEnabled = phaseTookQueryParamEnabled; + } + /** * Returns a threshold that enforces a pre-filter roundtrip to pre-filter search shards based on query rewriting if the number of shards * the search request expands to exceeds the threshold, or null if the threshold is unspecified. @@ -719,7 +751,8 @@ public boolean equals(Object o) { && absoluteStartMillis == that.absoluteStartMillis && ccsMinimizeRoundtrips == that.ccsMinimizeRoundtrips && Objects.equals(cancelAfterTimeInterval, that.cancelAfterTimeInterval) - && Objects.equals(pipeline, that.pipeline); + && Objects.equals(pipeline, that.pipeline) + && Objects.equals(phaseTookQueryParamEnabled, that.phaseTookQueryParamEnabled); } @Override @@ -740,7 +773,8 @@ public int hashCode() { localClusterAlias, absoluteStartMillis, ccsMinimizeRoundtrips, - cancelAfterTimeInterval + cancelAfterTimeInterval, + phaseTookQueryParamEnabled ); } @@ -783,6 +817,8 @@ public String toString() { + cancelAfterTimeInterval + ", pipeline=" + pipeline + + ", phaseTookQueryParamEnabled=" + + phaseTookQueryParamEnabled + "}"; } } diff --git a/server/src/main/java/org/opensearch/action/search/SearchResponse.java b/server/src/main/java/org/opensearch/action/search/SearchResponse.java index a546311a1f668..067141025afb4 100644 --- a/server/src/main/java/org/opensearch/action/search/SearchResponse.java +++ b/server/src/main/java/org/opensearch/action/search/SearchResponse.java @@ -94,6 +94,7 @@ public class SearchResponse extends ActionResponse implements StatusToXContentOb private final ShardSearchFailure[] shardFailures; private final Clusters clusters; private final long tookInMillis; + private final PhaseTook phaseTook; public SearchResponse(StreamInput in) throws IOException { super(in); @@ -112,6 +113,7 @@ public SearchResponse(StreamInput in) throws IOException { clusters = new Clusters(in); scrollId = in.readOptionalString(); tookInMillis = in.readVLong(); + phaseTook = new PhaseTook(in); skippedShards = in.readVInt(); pointInTimeId = in.readOptionalString(); } @@ -126,7 +128,18 @@ public SearchResponse( ShardSearchFailure[] shardFailures, Clusters clusters ) { - this(internalResponse, scrollId, totalShards, successfulShards, skippedShards, tookInMillis, shardFailures, clusters, null); + this( + internalResponse, + scrollId, + totalShards, + successfulShards, + skippedShards, + tookInMillis, + SearchResponse.PhaseTook.NULL, + shardFailures, + clusters, + null + ); } public SearchResponse( @@ -136,6 +149,7 @@ public SearchResponse( int successfulShards, int skippedShards, long tookInMillis, + PhaseTook phaseTook, ShardSearchFailure[] shardFailures, Clusters clusters, String pointInTimeId @@ -148,6 +162,7 @@ public SearchResponse( this.successfulShards = successfulShards; this.skippedShards = skippedShards; this.tookInMillis = tookInMillis; + this.phaseTook = phaseTook; this.shardFailures = shardFailures; assert skippedShards <= totalShards : "skipped: " + skippedShards + " total: " + totalShards; assert scrollId == null || pointInTimeId == null : "SearchResponse can't have both scrollId [" @@ -210,6 +225,13 @@ public TimeValue getTook() { return new TimeValue(tookInMillis); } + /** + * How long the request took in each search phase. + */ + public PhaseTook getPhaseTook() { + return phaseTook; + } + /** * The total number of shards the search was executed on. */ @@ -298,6 +320,9 @@ public XContentBuilder innerToXContent(XContentBuilder builder, Params params) t builder.field(POINT_IN_TIME_ID.getPreferredName(), pointInTimeId); } builder.field(TOOK.getPreferredName(), tookInMillis); + if (phaseTook.equals(PhaseTook.NULL) == false) { + phaseTook.toXContent(builder, params); + } builder.field(TIMED_OUT.getPreferredName(), isTimedOut()); if (isTerminatedEarly() != null) { builder.field(TERMINATED_EARLY.getPreferredName(), isTerminatedEarly()); @@ -337,6 +362,7 @@ public static SearchResponse innerFromXContent(XContentParser parser) throws IOE Boolean terminatedEarly = null; int numReducePhases = 1; long tookInMillis = -1; + PhaseTook phaseTook = PhaseTook.NULL; int successfulShards = -1; int totalShards = -1; int skippedShards = 0; // 0 for BWC @@ -401,6 +427,35 @@ public static SearchResponse innerFromXContent(XContentParser parser) throws IOE parser.skipChildren(); } } + } else if (PhaseTook.PHASE_TOOK.match(currentFieldName, parser.getDeprecationHandler())) { + long dfsPreQueryTotal = -1; + long canMatchTotal = -1; + long queryTotal = -1; + long fetchTotal = -1; + long expandSearchTotal = -1; + + while ((token = parser.nextToken()) != Token.END_OBJECT) { + if (token == Token.FIELD_NAME) { + currentFieldName = parser.currentName(); + } else if (token.isValue()) { + if (PhaseTook.DFS_PREQUERY_FIELD.match(currentFieldName, parser.getDeprecationHandler())) { + dfsPreQueryTotal = parser.longValue(); // we don't need it but need to consume it + } else if (PhaseTook.CAN_MATCH_FIELD.match(currentFieldName, parser.getDeprecationHandler())) { + canMatchTotal = parser.longValue(); + } else if (PhaseTook.QUERY_FIELD.match(currentFieldName, parser.getDeprecationHandler())) { + queryTotal = parser.longValue(); + } else if (PhaseTook.FETCH_FIELD.match(currentFieldName, parser.getDeprecationHandler())) { + fetchTotal = parser.longValue(); + } else if (PhaseTook.EXPAND_FIELD.match(currentFieldName, parser.getDeprecationHandler())) { + expandSearchTotal = parser.longValue(); + } else { + parser.skipChildren(); + } + } else { + parser.skipChildren(); + } + } + phaseTook = new PhaseTook(dfsPreQueryTotal, canMatchTotal, queryTotal, fetchTotal, expandSearchTotal); } else if (Clusters._CLUSTERS_FIELD.match(currentFieldName, parser.getDeprecationHandler())) { int successful = -1; int total = -1; @@ -472,6 +527,7 @@ public static SearchResponse innerFromXContent(XContentParser parser) throws IOE successfulShards, skippedShards, tookInMillis, + phaseTook, failures.toArray(ShardSearchFailure.EMPTY_ARRAY), clusters, searchContextId @@ -491,6 +547,7 @@ public void writeTo(StreamOutput out) throws IOException { clusters.writeTo(out); out.writeOptionalString(scrollId); out.writeVLong(tookInMillis); + phaseTook.writeTo(out); out.writeVInt(skippedShards); out.writeOptionalString(pointInTimeId); } @@ -604,6 +661,118 @@ public String toString() { } } + /** + * Holds info about the clusters that the search was executed on: how many in total, how many of them were successful + * and how many of them were skipped. + * + * @opensearch.internal + */ + public static class PhaseTook implements ToXContentFragment, Writeable { + public static final PhaseTook NULL = new PhaseTook(-1, -1, -1, -1, -1); + + static final ParseField PHASE_TOOK = new ParseField("phase_took"); + static final ParseField DFS_PREQUERY_FIELD = new ParseField("dfs_prequery"); + static final ParseField CAN_MATCH_FIELD = new ParseField("can_match"); + static final ParseField QUERY_FIELD = new ParseField("query"); + static final ParseField FETCH_FIELD = new ParseField("fetch"); + static final ParseField EXPAND_FIELD = new ParseField("expand_search"); + + private final long dfsPreQueryTotal; + private final long canMatchTotal; + private final long queryTotal; + private final long fetchTotal; + private final long expandSearchTotal; + + public PhaseTook(long dfsPreQueryTotal, long canMatchTotal, long queryTotal, long fetchTotal, long expandSearchTotal) { + this.dfsPreQueryTotal = dfsPreQueryTotal; + this.canMatchTotal = canMatchTotal; + this.queryTotal = queryTotal; + this.fetchTotal = fetchTotal; + this.expandSearchTotal = expandSearchTotal; + } + + private PhaseTook(StreamInput in) throws IOException { + this(in.readLong(), in.readLong(), in.readLong(), in.readLong(), in.readLong()); + } + + @Override + public void writeTo(StreamOutput out) throws IOException { + out.writeLong(dfsPreQueryTotal); + out.writeLong(canMatchTotal); + out.writeLong(queryTotal); + out.writeLong(fetchTotal); + out.writeLong(expandSearchTotal); + } + + @Override + public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { + builder.startObject(PHASE_TOOK.getPreferredName()); + builder.field(DFS_PREQUERY_FIELD.getPreferredName(), dfsPreQueryTotal); + builder.field(CAN_MATCH_FIELD.getPreferredName(), canMatchTotal); + builder.field(QUERY_FIELD.getPreferredName(), queryTotal); + builder.field(FETCH_FIELD.getPreferredName(), fetchTotal); + builder.field(EXPAND_FIELD.getPreferredName(), expandSearchTotal); + builder.endObject(); + return builder; + } + + /** + * Returns time spent in DFS Prequery phase during the execution of the search request + */ + public long getDfsPreQueryTotal() { + return dfsPreQueryTotal; + } + + /** + * Returns time spent in canMatch phase during the execution of the search request + */ + public long getCanMatchTotal() { + return canMatchTotal; + } + + /** + * Returns time spent in query phase during the execution of the search request + */ + public long getQueryTotal() { + return queryTotal; + } + + /** + * Returns time spent in fetch phase during the execution of the search request + */ + public long getFetchTotal() { + return fetchTotal; + } + + /** + * Returns time spent in expand phase during the execution of the search request + */ + public long getExpandSearchTotal() { + return expandSearchTotal; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + PhaseTook phaseTook = (PhaseTook) o; + return dfsPreQueryTotal == phaseTook.dfsPreQueryTotal + && queryTotal == phaseTook.queryTotal + && canMatchTotal == phaseTook.canMatchTotal + && fetchTotal == phaseTook.fetchTotal + && expandSearchTotal == phaseTook.expandSearchTotal; + } + + @Override + public int hashCode() { + return Objects.hash(dfsPreQueryTotal, queryTotal, canMatchTotal, fetchTotal, expandSearchTotal); + } + } + static SearchResponse empty(Supplier tookInMillisSupplier, Clusters clusters) { SearchHits searchHits = new SearchHits(new SearchHit[0], new TotalHits(0L, TotalHits.Relation.EQUAL_TO), Float.NaN); InternalSearchResponse internalSearchResponse = new InternalSearchResponse( @@ -622,6 +791,7 @@ static SearchResponse empty(Supplier tookInMillisSupplier, Clusters cluste 0, 0, tookInMillisSupplier.get(), + PhaseTook.NULL, ShardSearchFailure.EMPTY_ARRAY, clusters, null diff --git a/server/src/main/java/org/opensearch/action/search/SearchResponseMerger.java b/server/src/main/java/org/opensearch/action/search/SearchResponseMerger.java index f90e98106f93f..054bd578cc56c 100644 --- a/server/src/main/java/org/opensearch/action/search/SearchResponseMerger.java +++ b/server/src/main/java/org/opensearch/action/search/SearchResponseMerger.java @@ -236,6 +236,7 @@ SearchResponse getMergedResponse(SearchResponse.Clusters clusters) { successfulShards, skippedShards, tookInMillis, + searchTimeProvider.getPhaseTook(), shardFailures, clusters, null diff --git a/server/src/main/java/org/opensearch/action/search/SearchScrollAsyncAction.java b/server/src/main/java/org/opensearch/action/search/SearchScrollAsyncAction.java index 7329a03f7e281..3059b6dbb055c 100644 --- a/server/src/main/java/org/opensearch/action/search/SearchScrollAsyncAction.java +++ b/server/src/main/java/org/opensearch/action/search/SearchScrollAsyncAction.java @@ -299,6 +299,7 @@ protected final void sendResponse( successfulOps.get(), 0, buildTookInMillis(), + SearchResponse.PhaseTook.NULL, buildShardFailures(), SearchResponse.Clusters.EMPTY, null diff --git a/server/src/main/java/org/opensearch/action/search/TransportSearchAction.java b/server/src/main/java/org/opensearch/action/search/TransportSearchAction.java index 761709d8c5d60..72885da560cb4 100644 --- a/server/src/main/java/org/opensearch/action/search/TransportSearchAction.java +++ b/server/src/main/java/org/opensearch/action/search/TransportSearchAction.java @@ -57,6 +57,7 @@ import org.opensearch.cluster.service.ClusterService; import org.opensearch.common.Nullable; import org.opensearch.common.inject.Inject; +import org.opensearch.common.metrics.CounterMetric; import org.opensearch.common.settings.Setting; import org.opensearch.common.settings.Setting.Property; import org.opensearch.common.unit.TimeValue; @@ -109,6 +110,7 @@ import java.util.concurrent.atomic.AtomicReference; import java.util.function.BiConsumer; import java.util.function.BiFunction; +import java.util.function.Consumer; import java.util.function.Function; import java.util.function.LongSupplier; import java.util.stream.Collectors; @@ -153,6 +155,14 @@ public class TransportSearchAction extends HandledTransportAction SEARCH_PHASE_TOOK_ENABLED = Setting.boolSetting( + SEARCH_PHASE_TOOK_ENABLED_KEY, + false, + Property.Dynamic, + Property.NodeScope + ); + private final NodeClient client; private final ThreadPool threadPool; private final ClusterService clusterService; @@ -260,11 +270,12 @@ private Map resolveIndexBoosts(SearchRequest searchRequest, Clust * * @opensearch.internal */ - static final class SearchTimeProvider { + static final class SearchTimeProvider implements SearchRequestOperationsListener { private final long absoluteStartMillis; private final long relativeStartNanos; private final LongSupplier relativeCurrentNanosProvider; + private boolean phaseTookEnabled = false; /** * Instantiates a new search time provider. The absolute start time is the real clock time @@ -290,6 +301,118 @@ long getAbsoluteStartMillis() { long buildTookInMillis() { return TimeUnit.NANOSECONDS.toMillis(relativeCurrentNanosProvider.getAsLong() - relativeStartNanos); } + + public void setPhaseTookEnabled(boolean phaseTookEnabled) { + this.phaseTookEnabled = phaseTookEnabled; + } + + public boolean isPhaseTookEnabled() { + return phaseTookEnabled; + } + + SearchResponse.PhaseTook getPhaseTook() { + if (phaseTookEnabled) { + return new SearchResponse.PhaseTook( + totalStats.dfsPreQueryTotal.count(), + totalStats.canMatchTotal.count(), + totalStats.queryTotal.count(), + totalStats.fetchTotal.count(), + totalStats.expandSearchTotal.count() + ); + } else { + return SearchResponse.PhaseTook.NULL; + } + } + + public SearchTimeProvider.RequestStatsHolder totalStats = new RequestStatsHolder(); + + public static final class RequestStatsHolder { + public CounterMetric dfsPreQueryTotal = new CounterMetric(); + public CounterMetric canMatchTotal = new CounterMetric(); + public CounterMetric queryTotal = new CounterMetric(); + public CounterMetric fetchTotal = new CounterMetric(); + public CounterMetric expandSearchTotal = new CounterMetric(); + } + + // call these to populate return values + public long getDFSPreQueryTotal() { + return totalStats.dfsPreQueryTotal.count(); + } + + public long getCanMatchTotal() { + return totalStats.canMatchTotal.count(); + } + + public long getQueryTotal() { + return totalStats.queryTotal.count(); + } + + public long getFetchTotal() { + return totalStats.fetchTotal.count(); + } + + public long getExpandSearchTotal() { + return totalStats.expandSearchTotal.count(); + } + + private void computeStats(Consumer consumer) { + consumer.accept(totalStats); + } + + @Override + public void onDFSPreQueryPhaseStart(SearchPhaseContext context) {} + + @Override + public void onDFSPreQueryPhaseEnd(SearchPhaseContext context, long tookTime) { + computeStats(statsHolder -> { totalStats.dfsPreQueryTotal.inc(tookTime); }); + } + + @Override + public void onDFSPreQueryPhaseFailure(SearchPhaseContext context) {} + + @Override + public void onCanMatchPhaseStart(SearchPhaseContext context) {} + + @Override + public void onCanMatchPhaseEnd(SearchPhaseContext context, long tookTime) { + computeStats(statsHolder -> { totalStats.canMatchTotal.inc(tookTime); }); + } + + @Override + public void onCanMatchPhaseFailure(SearchPhaseContext context) {} + + @Override + public void onQueryPhaseStart(SearchPhaseContext context) {} + + @Override + public void onQueryPhaseEnd(SearchPhaseContext context, long tookTime) { + computeStats(statsHolder -> { totalStats.queryTotal.inc(tookTime); }); + } + + @Override + public void onQueryPhaseFailure(SearchPhaseContext context) {} + + @Override + public void onFetchPhaseStart(SearchPhaseContext context) {} + + @Override + public void onFetchPhaseEnd(SearchPhaseContext context, long tookTime) { + computeStats(statsHolder -> { totalStats.fetchTotal.inc(tookTime); }); + } + + @Override + public void onFetchPhaseFailure(SearchPhaseContext context) {} + + @Override + public void onExpandSearchPhaseStart(SearchPhaseContext context) {} + + @Override + public void onExpandSearchPhaseEnd(SearchPhaseContext context, long tookTime) { + computeStats(statsHolder -> { totalStats.expandSearchTotal.inc(tookTime); }); + } + + @Override + public void onExpandSearchPhaseFailure(SearchPhaseContext context) {} } @Override @@ -350,6 +473,12 @@ public AbstractSearchAsyncAction asyncSearchAction( ThreadPool threadPool, SearchResponse.Clusters clusters ) { + if (searchRequest.isPhaseTookQueryParamEnabled() == SearchRequest.ParamValue.TRUE + || (searchRequest.isPhaseTookQueryParamEnabled() == SearchRequest.ParamValue.UNSET + && clusterService.getClusterSettings().get(TransportSearchAction.SEARCH_PHASE_TOOK_ENABLED))) { + timeProvider.setPhaseTookEnabled(true); + } + return new AbstractSearchAsyncAction( actionName, logger, @@ -412,6 +541,11 @@ private void executeRequest( relativeStartNanos, System::nanoTime ); + if (originalSearchRequest.isPhaseTookQueryParamEnabled() == SearchRequest.ParamValue.TRUE + || (originalSearchRequest.isPhaseTookQueryParamEnabled() == SearchRequest.ParamValue.UNSET + && clusterService.getClusterSettings().get(TransportSearchAction.SEARCH_PHASE_TOOK_ENABLED))) { + timeProvider.setPhaseTookEnabled(true); + } PipelinedRequest searchRequest; ActionListener listener; try { @@ -615,6 +749,7 @@ public void onResponse(SearchResponse searchResponse) { searchResponse.getSuccessfulShards(), searchResponse.getSkippedShards(), timeProvider.buildTookInMillis(), + timeProvider.getPhaseTook(), searchResponse.getShardFailures(), new SearchResponse.Clusters(1, 1, 0), searchResponse.pointInTimeId() diff --git a/server/src/main/java/org/opensearch/common/settings/ClusterSettings.java b/server/src/main/java/org/opensearch/common/settings/ClusterSettings.java index 22e65b2c04668..25787c04f3534 100644 --- a/server/src/main/java/org/opensearch/common/settings/ClusterSettings.java +++ b/server/src/main/java/org/opensearch/common/settings/ClusterSettings.java @@ -374,6 +374,7 @@ public void apply(Settings value, Settings current, Settings previous) { TransportSearchAction.SHARD_COUNT_LIMIT_SETTING, TransportSearchAction.SEARCH_CANCEL_AFTER_TIME_INTERVAL_SETTING, TransportSearchAction.SEARCH_REQUEST_STATS_ENABLED, + TransportSearchAction.SEARCH_PHASE_TOOK_ENABLED, RemoteClusterService.REMOTE_CLUSTER_SKIP_UNAVAILABLE, SniffConnectionStrategy.REMOTE_CONNECTIONS_PER_CLUSTER, RemoteClusterService.REMOTE_INITIAL_CONNECTION_TIMEOUT_SETTING, diff --git a/server/src/main/java/org/opensearch/rest/action/search/RestSearchAction.java b/server/src/main/java/org/opensearch/rest/action/search/RestSearchAction.java index ebfd082d974fd..cbbac35a1590c 100644 --- a/server/src/main/java/org/opensearch/rest/action/search/RestSearchAction.java +++ b/server/src/main/java/org/opensearch/rest/action/search/RestSearchAction.java @@ -180,6 +180,12 @@ public static void parseSearchRequest( searchRequest.allowPartialSearchResults(request.paramAsBoolean("allow_partial_search_results", null)); } + if (request.hasParam("phase_took")) { + // only set if we have the parameter passed to override the cluster-level default + // else phaseTookQueryParamEnabled = null + searchRequest.setPhaseTookQueryParamEnabled(request.paramAsBoolean("phase_took", true)); + } + // do not allow 'query_and_fetch' or 'dfs_query_and_fetch' search types // from the REST layer. these modes are an internal optimization and should // not be specified explicitly by the user.