org.elasticsearch.rest.action.search.RestMultiSearchAction Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of elasticsearch Show documentation
Show all versions of elasticsearch Show documentation
Elasticsearch subproject :server
/*
* Licensed to Elasticsearch under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.elasticsearch.rest.action.search;
import org.apache.logging.log4j.LogManager;
import org.elasticsearch.action.search.MultiSearchRequest;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.support.IndicesOptions;
import org.elasticsearch.client.node.NodeClient;
import org.elasticsearch.common.CheckedBiConsumer;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.collect.Tuple;
import org.elasticsearch.common.logging.DeprecationLogger;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContent;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.rest.BaseRestHandler;
import org.elasticsearch.rest.RestController;
import org.elasticsearch.rest.RestRequest;
import org.elasticsearch.rest.action.RestToXContentListener;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import static org.elasticsearch.rest.RestRequest.Method.GET;
import static org.elasticsearch.rest.RestRequest.Method.POST;
public class RestMultiSearchAction extends BaseRestHandler {
private static final DeprecationLogger deprecationLogger = new DeprecationLogger(
LogManager.getLogger(RestMultiSearchAction.class));
static final String TYPES_DEPRECATION_MESSAGE = "[types removal]" +
" Specifying types in multi search requests is deprecated.";
private static final Set RESPONSE_PARAMS;
static {
final Set responseParams = new HashSet<>(
Arrays.asList(RestSearchAction.TYPED_KEYS_PARAM, RestSearchAction.TOTAL_HITS_AS_INT_PARAM)
);
RESPONSE_PARAMS = Collections.unmodifiableSet(responseParams);
}
private final boolean allowExplicitIndex;
public RestMultiSearchAction(Settings settings, RestController controller) {
controller.registerHandler(GET, "/_msearch", this);
controller.registerHandler(POST, "/_msearch", this);
controller.registerHandler(GET, "/{index}/_msearch", this);
controller.registerHandler(POST, "/{index}/_msearch", this);
// Deprecated typed endpoints.
controller.registerHandler(GET, "/{index}/{type}/_msearch", this);
controller.registerHandler(POST, "/{index}/{type}/_msearch", this);
this.allowExplicitIndex = MULTI_ALLOW_EXPLICIT_INDEX.get(settings);
}
@Override
public String getName() {
return "msearch_action";
}
@Override
public RestChannelConsumer prepareRequest(final RestRequest request, final NodeClient client) throws IOException {
MultiSearchRequest multiSearchRequest = parseRequest(request, allowExplicitIndex);
// Emit a single deprecation message if any search request contains types.
for (SearchRequest searchRequest : multiSearchRequest.requests()) {
if (searchRequest.types().length > 0) {
deprecationLogger.deprecatedAndMaybeLog("msearch_with_types", TYPES_DEPRECATION_MESSAGE);
break;
}
}
return channel -> client.multiSearch(multiSearchRequest, new RestToXContentListener<>(channel));
}
/**
* Parses a {@link RestRequest} body and returns a {@link MultiSearchRequest}
*/
public static MultiSearchRequest parseRequest(RestRequest restRequest, boolean allowExplicitIndex) throws IOException {
MultiSearchRequest multiRequest = new MultiSearchRequest();
IndicesOptions indicesOptions = IndicesOptions.fromRequest(restRequest, multiRequest.indicesOptions());
multiRequest.indicesOptions(indicesOptions);
if (restRequest.hasParam("max_concurrent_searches")) {
multiRequest.maxConcurrentSearchRequests(restRequest.paramAsInt("max_concurrent_searches", 0));
}
int preFilterShardSize = restRequest.paramAsInt("pre_filter_shard_size", SearchRequest.DEFAULT_PRE_FILTER_SHARD_SIZE);
final Integer maxConcurrentShardRequests;
if (restRequest.hasParam("max_concurrent_shard_requests")) {
// only set if we have the parameter since we auto adjust the max concurrency on the coordinator
// based on the number of nodes in the cluster
maxConcurrentShardRequests = restRequest.paramAsInt("max_concurrent_shard_requests", Integer.MIN_VALUE);
} else {
maxConcurrentShardRequests = null;
}
parseMultiLineRequest(restRequest, multiRequest.indicesOptions(), allowExplicitIndex, (searchRequest, parser) -> {
searchRequest.source(SearchSourceBuilder.fromXContent(parser, false));
RestSearchAction.checkRestTotalHits(restRequest, searchRequest);
multiRequest.add(searchRequest);
});
List requests = multiRequest.requests();
preFilterShardSize = Math.max(1, preFilterShardSize / (requests.size()+1));
for (SearchRequest request : requests) {
// preserve if it's set on the request
request.setPreFilterShardSize(Math.min(preFilterShardSize, request.getPreFilterShardSize()));
if (maxConcurrentShardRequests != null) {
request.setMaxConcurrentShardRequests(maxConcurrentShardRequests);
}
}
return multiRequest;
}
/**
* Parses a multi-line {@link RestRequest} body, instantiating a {@link SearchRequest} for each line and applying the given consumer.
*/
public static void parseMultiLineRequest(RestRequest request, IndicesOptions indicesOptions, boolean allowExplicitIndex,
CheckedBiConsumer consumer) throws IOException {
String[] indices = Strings.splitStringByCommaToArray(request.param("index"));
String[] types = Strings.splitStringByCommaToArray(request.param("type"));
String searchType = request.param("search_type");
boolean ccsMinimizeRoundtrips = request.paramAsBoolean("ccs_minimize_roundtrips", true);
String routing = request.param("routing");
final Tuple sourceTuple = request.contentOrSourceParam();
final XContent xContent = sourceTuple.v1().xContent();
final BytesReference data = sourceTuple.v2();
MultiSearchRequest.readMultiLineFormat(data, xContent, consumer, indices, indicesOptions, types, routing,
searchType, ccsMinimizeRoundtrips, request.getXContentRegistry(), allowExplicitIndex, deprecationLogger);
}
@Override
public boolean supportsContentStream() {
return true;
}
@Override
protected Set responseParams() {
return RESPONSE_PARAMS;
}
}