Merge pull request #16873 from abeyad/suggester-wiring-refactoring

Change internal representation of suggesters
This commit is contained in:
Ali Beyad 2016-03-11 12:34:35 -05:00
commit 31dcb3e18b
35 changed files with 465 additions and 330 deletions

View File

@ -208,7 +208,6 @@
<suppress files="core[/\\]src[/\\]main[/\\]java[/\\]org[/\\]elasticsearch[/\\]action[/\\]search[/\\]TransportClearScrollAction.java" checks="LineLength" />
<suppress files="core[/\\]src[/\\]main[/\\]java[/\\]org[/\\]elasticsearch[/\\]action[/\\]search[/\\]TransportMultiSearchAction.java" checks="LineLength" />
<suppress files="core[/\\]src[/\\]main[/\\]java[/\\]org[/\\]elasticsearch[/\\]action[/\\]suggest[/\\]SuggestResponse.java" checks="LineLength" />
<suppress files="core[/\\]src[/\\]main[/\\]java[/\\]org[/\\]elasticsearch[/\\]action[/\\]suggest[/\\]TransportSuggestAction.java" checks="LineLength" />
<suppress files="core[/\\]src[/\\]main[/\\]java[/\\]org[/\\]elasticsearch[/\\]action[/\\]support[/\\]ActionFilter.java" checks="LineLength" />
<suppress files="core[/\\]src[/\\]main[/\\]java[/\\]org[/\\]elasticsearch[/\\]action[/\\]support[/\\]AutoCreateIndex.java" checks="LineLength" />
<suppress files="core[/\\]src[/\\]main[/\\]java[/\\]org[/\\]elasticsearch[/\\]action[/\\]support[/\\]DelegatingActionListener.java" checks="LineLength" />
@ -269,7 +268,6 @@
<suppress files="core[/\\]src[/\\]main[/\\]java[/\\]org[/\\]elasticsearch[/\\]cache[/\\]recycler[/\\]PageCacheRecycler.java" checks="LineLength" />
<suppress files="core[/\\]src[/\\]main[/\\]java[/\\]org[/\\]elasticsearch[/\\]client[/\\]ElasticsearchClient.java" checks="LineLength" />
<suppress files="core[/\\]src[/\\]main[/\\]java[/\\]org[/\\]elasticsearch[/\\]client[/\\]FilterClient.java" checks="LineLength" />
<suppress files="core[/\\]src[/\\]main[/\\]java[/\\]org[/\\]elasticsearch[/\\]client[/\\]Requests.java" checks="LineLength" />
<suppress files="core[/\\]src[/\\]main[/\\]java[/\\]org[/\\]elasticsearch[/\\]client[/\\]node[/\\]NodeClient.java" checks="LineLength" />
<suppress files="core[/\\]src[/\\]main[/\\]java[/\\]org[/\\]elasticsearch[/\\]client[/\\]support[/\\]AbstractClient.java" checks="LineLength" />
<suppress files="core[/\\]src[/\\]main[/\\]java[/\\]org[/\\]elasticsearch[/\\]client[/\\]transport[/\\]TransportClient.java" checks="LineLength" />
@ -1399,7 +1397,6 @@
<suppress files="core[/\\]src[/\\]test[/\\]java[/\\]org[/\\]elasticsearch[/\\]search[/\\]basic[/\\]SearchWithRandomIOExceptionsIT.java" checks="LineLength" />
<suppress files="core[/\\]src[/\\]test[/\\]java[/\\]org[/\\]elasticsearch[/\\]search[/\\]basic[/\\]TransportSearchFailuresIT.java" checks="LineLength" />
<suppress files="core[/\\]src[/\\]test[/\\]java[/\\]org[/\\]elasticsearch[/\\]search[/\\]basic[/\\]TransportTwoNodesSearchIT.java" checks="LineLength" />
<suppress files="core[/\\]src[/\\]test[/\\]java[/\\]org[/\\]elasticsearch[/\\]search[/\\]builder[/\\]SearchSourceBuilderTests.java" checks="LineLength" />
<suppress files="core[/\\]src[/\\]test[/\\]java[/\\]org[/\\]elasticsearch[/\\]search[/\\]child[/\\]ChildQuerySearchIT.java" checks="LineLength" />
<suppress files="core[/\\]src[/\\]test[/\\]java[/\\]org[/\\]elasticsearch[/\\]search[/\\]child[/\\]ParentFieldLoadingIT.java" checks="LineLength" />
<suppress files="core[/\\]src[/\\]test[/\\]java[/\\]org[/\\]elasticsearch[/\\]search[/\\]fetch[/\\]FetchSubPhasePluginIT.java" checks="LineLength" />
@ -1431,7 +1428,6 @@
<suppress files="core[/\\]src[/\\]test[/\\]java[/\\]org[/\\]elasticsearch[/\\]search[/\\]suggest[/\\]CompletionSuggestSearchIT.java" checks="LineLength" />
<suppress files="core[/\\]src[/\\]test[/\\]java[/\\]org[/\\]elasticsearch[/\\]search[/\\]suggest[/\\]ContextCompletionSuggestSearchIT.java" checks="LineLength" />
<suppress files="core[/\\]src[/\\]test[/\\]java[/\\]org[/\\]elasticsearch[/\\]search[/\\]suggest[/\\]CustomSuggester.java" checks="LineLength" />
<suppress files="core[/\\]src[/\\]test[/\\]java[/\\]org[/\\]elasticsearch[/\\]search[/\\]suggest[/\\]CustomSuggesterSearchIT.java" checks="LineLength" />
<suppress files="core[/\\]src[/\\]test[/\\]java[/\\]org[/\\]elasticsearch[/\\]search[/\\]suggest[/\\]completion[/\\]CategoryContextMappingTests.java" checks="LineLength" />
<suppress files="core[/\\]src[/\\]test[/\\]java[/\\]org[/\\]elasticsearch[/\\]search[/\\]suggest[/\\]completion[/\\]GeoContextMappingTests.java" checks="LineLength" />
<suppress files="core[/\\]src[/\\]test[/\\]java[/\\]org[/\\]elasticsearch[/\\]search[/\\]suggest[/\\]phrase[/\\]DirectCandidateGeneratorTests.java" checks="LineLength" />

View File

@ -20,10 +20,10 @@
package org.elasticsearch.action.suggest;
import org.elasticsearch.action.support.broadcast.BroadcastShardRequest;
import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.index.shard.ShardId;
import org.elasticsearch.search.suggest.SuggestBuilder;
import java.io.IOException;
@ -32,29 +32,29 @@ import java.io.IOException;
*/
public final class ShardSuggestRequest extends BroadcastShardRequest {
private BytesReference suggestSource;
private SuggestBuilder suggest;
public ShardSuggestRequest() {
}
ShardSuggestRequest(ShardId shardId, SuggestRequest request) {
super(shardId, request);
this.suggestSource = request.suggest();
this.suggest = request.suggest();
}
public BytesReference suggest() {
return suggestSource;
public SuggestBuilder suggest() {
return suggest;
}
@Override
public void readFrom(StreamInput in) throws IOException {
super.readFrom(in);
suggestSource = in.readBytesReference();
suggest = SuggestBuilder.PROTOTYPE.readFrom(in);
}
@Override
public void writeTo(StreamOutput out) throws IOException {
super.writeTo(out);
out.writeBytesReference(suggestSource);
suggest.writeTo(out);
}
}

View File

@ -21,28 +21,25 @@ package org.elasticsearch.action.suggest;
import org.elasticsearch.action.ActionRequestValidationException;
import org.elasticsearch.action.support.broadcast.BroadcastRequest;
import org.elasticsearch.client.Requests;
import org.elasticsearch.common.Nullable;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.bytes.BytesArray;
import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.xcontent.XContentHelper;
import org.elasticsearch.common.xcontent.ToXContent;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.json.JsonXContent;
import org.elasticsearch.search.suggest.SuggestBuilder;
import org.elasticsearch.search.suggest.SuggestionBuilder;
import java.io.IOException;
import java.util.Arrays;
import java.util.Objects;
/**
* A request to get suggestions for corrections of phrases. Best created with
* {@link org.elasticsearch.client.Requests#suggestRequest(String...)}.
* <p>
* The request requires the suggest query source to be set either using
* {@link #suggest(org.elasticsearch.common.bytes.BytesReference)} / {@link #suggest(org.elasticsearch.common.bytes.BytesReference)}
* or by using {@link #suggest(org.elasticsearch.search.suggest.SuggestBuilder)}
* (Best created using the {link @org.elasticsearch.search.suggest.SuggestBuilders)}).
* The request requires the suggest query source to be set using
* {@link #suggest(org.elasticsearch.search.suggest.SuggestBuilder)}
*
* @see SuggestResponse
* @see org.elasticsearch.client.Client#suggest(SuggestRequest)
@ -57,7 +54,7 @@ public final class SuggestRequest extends BroadcastRequest<SuggestRequest> {
@Nullable
private String preference;
private BytesReference suggestSource;
private SuggestBuilder suggest;
public SuggestRequest() {
}
@ -77,40 +74,21 @@ public final class SuggestRequest extends BroadcastRequest<SuggestRequest> {
}
/**
* The Phrase to get correction suggestions for
* The suggestion query to get correction suggestions for
*/
public BytesReference suggest() {
return suggestSource;
public SuggestBuilder suggest() {
return suggest;
}
/**
* set a new source for the suggest query
* set a new source for the suggest query
*/
public SuggestRequest suggest(BytesReference suggestSource) {
this.suggestSource = suggestSource;
public SuggestRequest suggest(SuggestBuilder suggest) {
Objects.requireNonNull(suggest, "suggest must not be null");
this.suggest = suggest;
return this;
}
/**
* set a new source using a {@link org.elasticsearch.search.suggest.SuggestBuilder}
* for phrase and term suggestion lookup
*/
public SuggestRequest suggest(SuggestBuilder suggestBuilder) {
return suggest(suggestBuilder.buildAsBytes(Requests.CONTENT_TYPE));
}
/**
* set a new source using a {@link org.elasticsearch.search.suggest.SuggestionBuilder}
* for completion suggestion lookup
*/
public SuggestRequest suggest(SuggestionBuilder suggestionBuilder) {
return suggest(suggestionBuilder.buildAsBytes(Requests.CONTENT_TYPE));
}
public SuggestRequest suggest(String source) {
return suggest(new BytesArray(source));
}
/**
* A comma separated list of routing values to control the shards the search will be executed on.
*/
@ -148,25 +126,29 @@ public final class SuggestRequest extends BroadcastRequest<SuggestRequest> {
super.readFrom(in);
routing = in.readOptionalString();
preference = in.readOptionalString();
suggest(in.readBytesReference());
suggest = SuggestBuilder.PROTOTYPE.readFrom(in);
}
@Override
public void writeTo(StreamOutput out) throws IOException {
Objects.requireNonNull(suggest, "suggest must not be null");
super.writeTo(out);
out.writeOptionalString(routing);
out.writeOptionalString(preference);
out.writeBytesReference(suggestSource);
suggest.writeTo(out);
}
@Override
public String toString() {
Objects.requireNonNull(suggest, "suggest must not be null");
String sSource = "_na_";
try {
sSource = XContentHelper.convertToJson(suggestSource, false);
XContentBuilder builder = JsonXContent.contentBuilder();
builder = suggest.toXContent(builder, ToXContent.EMPTY_PARAMS);
sSource = builder.string();
} catch (Exception e) {
// ignore
}
return "[" + Arrays.toString(indices) + "]" + ", suggestSource[" + sSource + "]";
return "[" + Arrays.toString(indices) + "]" + ", suggest[" + sSource + "]";
}
}

View File

@ -19,18 +19,11 @@
package org.elasticsearch.action.suggest;
import org.elasticsearch.ElasticsearchException;
import org.elasticsearch.action.support.broadcast.BroadcastOperationRequestBuilder;
import org.elasticsearch.client.ElasticsearchClient;
import org.elasticsearch.client.Requests;
import org.elasticsearch.common.xcontent.ToXContent;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.search.suggest.SuggestBuilder;
import org.elasticsearch.search.suggest.SuggestionBuilder;
import java.io.IOException;
/**
* A suggest action request builder.
*/
@ -86,13 +79,7 @@ public class SuggestRequestBuilder extends BroadcastOperationRequestBuilder<Sugg
@Override
protected SuggestRequest beforeExecute(SuggestRequest request) {
try {
XContentBuilder builder = XContentFactory.contentBuilder(Requests.CONTENT_TYPE);
suggest.toXContent(builder, ToXContent.EMPTY_PARAMS);
request.suggest(builder.bytes());
} catch (IOException e) {
throw new ElasticsearchException("Unable to build suggestion request", e);
}
request.suggest(suggest);
return request;
}
}

View File

@ -32,17 +32,15 @@ import org.elasticsearch.cluster.block.ClusterBlockLevel;
import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver;
import org.elasticsearch.cluster.routing.GroupShardsIterator;
import org.elasticsearch.cluster.routing.ShardRouting;
import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.index.IndexService;
import org.elasticsearch.index.engine.Engine;
import org.elasticsearch.index.shard.IndexShard;
import org.elasticsearch.index.suggest.stats.ShardSuggestMetric;
import org.elasticsearch.indices.IndicesService;
import org.elasticsearch.search.suggest.Suggest;
import org.elasticsearch.search.suggest.SuggestBuilder;
import org.elasticsearch.search.suggest.SuggestPhase;
import org.elasticsearch.search.suggest.SuggestionSearchContext;
import org.elasticsearch.threadpool.ThreadPool;
@ -58,15 +56,16 @@ import java.util.concurrent.atomic.AtomicReferenceArray;
/**
* Defines the transport of a suggestion request across the cluster
*/
public class TransportSuggestAction extends TransportBroadcastAction<SuggestRequest, SuggestResponse, ShardSuggestRequest, ShardSuggestResponse> {
public class TransportSuggestAction
extends TransportBroadcastAction<SuggestRequest, SuggestResponse, ShardSuggestRequest, ShardSuggestResponse> {
private final IndicesService indicesService;
private final SuggestPhase suggestPhase;
@Inject
public TransportSuggestAction(Settings settings, ThreadPool threadPool, ClusterService clusterService, TransportService transportService,
IndicesService indicesService, SuggestPhase suggestPhase, ActionFilters actionFilters,
IndexNameExpressionResolver indexNameExpressionResolver) {
public TransportSuggestAction(Settings settings, ThreadPool threadPool, ClusterService clusterService,
TransportService transportService, IndicesService indicesService, SuggestPhase suggestPhase,
ActionFilters actionFilters, IndexNameExpressionResolver indexNameExpressionResolver) {
super(settings, SuggestAction.NAME, threadPool, clusterService, transportService, actionFilters, indexNameExpressionResolver,
SuggestRequest::new, ShardSuggestRequest::new, ThreadPool.Names.SUGGEST);
this.indicesService = indicesService;
@ -85,7 +84,8 @@ public class TransportSuggestAction extends TransportBroadcastAction<SuggestRequ
@Override
protected GroupShardsIterator shards(ClusterState clusterState, SuggestRequest request, String[] concreteIndices) {
Map<String, Set<String>> routingMap = indexNameExpressionResolver.resolveSearchRouting(clusterState, request.routing(), request.indices());
Map<String, Set<String>> routingMap =
indexNameExpressionResolver.resolveSearchRouting(clusterState, request.routing(), request.indices());
return clusterService.operationRouting().searchShards(clusterState, concreteIndices, routingMap, request.preference());
}
@ -124,7 +124,8 @@ public class TransportSuggestAction extends TransportBroadcastAction<SuggestRequ
}
}
return new SuggestResponse(new Suggest(Suggest.reduce(groupedSuggestions)), shardsResponses.length(), successfulShards, failedShards, shardFailures);
return new SuggestResponse(new Suggest(Suggest.reduce(groupedSuggestions)), shardsResponses.length(),
successfulShards, failedShards, shardFailures);
}
@Override
@ -134,15 +135,10 @@ public class TransportSuggestAction extends TransportBroadcastAction<SuggestRequ
ShardSuggestMetric suggestMetric = indexShard.getSuggestMetric();
suggestMetric.preSuggest();
long startTime = System.nanoTime();
XContentParser parser = null;
try (Engine.Searcher searcher = indexShard.acquireSearcher("suggest")) {
BytesReference suggest = request.suggest();
if (suggest != null && suggest.length() > 0) {
parser = XContentFactory.xContent(suggest).createParser(suggest);
if (parser.nextToken() != XContentParser.Token.START_OBJECT) {
throw new IllegalArgumentException("suggest content missing");
}
final SuggestionSearchContext context = suggestPhase.parseElement().parseInternal(parser, indexService.newQueryShardContext());
SuggestBuilder suggest = request.suggest();
if (suggest != null) {
final SuggestionSearchContext context = suggest.build(indexService.newQueryShardContext());
final Suggest result = suggestPhase.execute(context, searcher.searcher());
return new ShardSuggestResponse(request.shardId(), result);
}
@ -150,9 +146,6 @@ public class TransportSuggestAction extends TransportBroadcastAction<SuggestRequ
} catch (Throwable ex) {
throw new ElasticsearchException("failed to execute suggest", ex);
} finally {
if (parser != null) {
parser.close();
}
suggestMetric.postSuggest(System.nanoTime() - startTime);
}
}

View File

@ -62,6 +62,7 @@ import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchScrollRequest;
import org.elasticsearch.action.suggest.SuggestRequest;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.search.suggest.SuggestBuilder;
/**
* A handy one stop shop for creating requests (make sure to import static this class).
@ -127,7 +128,7 @@ public class Requests {
/**
* Creates a suggest request for getting suggestions from provided <code>indices</code>.
* The suggest query has to be set using the JSON source using {@link org.elasticsearch.action.suggest.SuggestRequest#suggest(org.elasticsearch.common.bytes.BytesReference)}.
* The suggest query has to be set using {@link org.elasticsearch.action.suggest.SuggestRequest#suggest(SuggestBuilder)}.
* @param indices The indices to suggest from. Use <tt>null</tt> or <tt>_all</tt> to execute against all indices
* @see org.elasticsearch.client.Client#suggest(org.elasticsearch.action.suggest.SuggestRequest)
*/
@ -342,7 +343,8 @@ public class Requests {
/**
* Creates a cluster health request.
*
* @param indices The indices to provide additional cluster health information for. Use <tt>null</tt> or <tt>_all</tt> to execute against all indices
* @param indices The indices to provide additional cluster health information for.
* Use <tt>null</tt> or <tt>_all</tt> to execute against all indices
* @return The cluster health request
* @see org.elasticsearch.client.ClusterAdminClient#health(org.elasticsearch.action.admin.cluster.health.ClusterHealthRequest)
*/

View File

@ -44,6 +44,7 @@ import org.elasticsearch.rest.action.support.RestToXContentListener;
import org.elasticsearch.script.Template;
import org.elasticsearch.search.aggregations.AggregatorParsers;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.suggest.Suggesters;
import java.util.Map;
@ -60,13 +61,14 @@ public class RestMultiSearchAction extends BaseRestHandler {
private final boolean allowExplicitIndex;
private final IndicesQueriesRegistry indicesQueriesRegistry;
private final AggregatorParsers aggParsers;
private final Suggesters suggesters;
@Inject
public RestMultiSearchAction(Settings settings, RestController controller, Client client, IndicesQueriesRegistry indicesQueriesRegistry,
AggregatorParsers aggParsers) {
AggregatorParsers aggParsers, Suggesters suggesters) {
super(settings, client);
this.aggParsers = aggParsers;
this.suggesters = suggesters;
controller.registerHandler(GET, "/_msearch", this);
controller.registerHandler(POST, "/_msearch", this);
@ -97,7 +99,7 @@ public class RestMultiSearchAction extends BaseRestHandler {
IndicesOptions indicesOptions = IndicesOptions.fromRequest(request, multiSearchRequest.indicesOptions());
parseRequest(multiSearchRequest, RestActions.getRestContent(request), isTemplateRequest, indices, types,
request.param("search_type"), request.param("routing"), indicesOptions, allowExplicitIndex, indicesQueriesRegistry,
parseFieldMatcher, aggParsers);
parseFieldMatcher, aggParsers, suggesters);
client.multiSearch(multiSearchRequest, new RestToXContentListener<>(channel));
}
@ -112,7 +114,8 @@ public class RestMultiSearchAction extends BaseRestHandler {
@Nullable String routing,
IndicesOptions indicesOptions,
boolean allowExplicitIndex, IndicesQueriesRegistry indicesQueriesRegistry,
ParseFieldMatcher parseFieldMatcher, AggregatorParsers aggParsers) throws Exception {
ParseFieldMatcher parseFieldMatcher, AggregatorParsers aggParsers,
Suggesters suggesters) throws Exception {
XContent xContent = XContentFactory.xContent(data);
int from = 0;
int length = data.length();
@ -193,7 +196,7 @@ public class RestMultiSearchAction extends BaseRestHandler {
} else {
try (XContentParser requestParser = XContentFactory.xContent(slice).createParser(slice)) {
queryParseContext.reset(requestParser);
searchRequest.source(SearchSourceBuilder.parseSearchSource(requestParser, queryParseContext, aggParsers));
searchRequest.source(SearchSourceBuilder.parseSearchSource(requestParser, queryParseContext, aggParsers, suggesters));
}
}
// move pointers

View File

@ -49,6 +49,7 @@ import org.elasticsearch.search.internal.SearchContext;
import org.elasticsearch.search.sort.SortOrder;
import org.elasticsearch.search.suggest.SuggestBuilder;
import org.elasticsearch.search.suggest.term.TermSuggestionBuilder.SuggestMode;
import org.elasticsearch.search.suggest.Suggesters;
import java.io.IOException;
import java.util.Arrays;
@ -65,13 +66,15 @@ public class RestSearchAction extends BaseRestHandler {
private final IndicesQueriesRegistry queryRegistry;
private final AggregatorParsers aggParsers;
private final Suggesters suggesters;
@Inject
public RestSearchAction(Settings settings, RestController controller, Client client, IndicesQueriesRegistry queryRegistry,
AggregatorParsers aggParsers) {
AggregatorParsers aggParsers, Suggesters suggesters) {
super(settings, client);
this.queryRegistry = queryRegistry;
this.aggParsers = aggParsers;
this.suggesters = suggesters;
controller.registerHandler(GET, "/_search", this);
controller.registerHandler(POST, "/_search", this);
controller.registerHandler(GET, "/{index}/_search", this);
@ -89,7 +92,7 @@ public class RestSearchAction extends BaseRestHandler {
@Override
public void handleRequest(final RestRequest request, final RestChannel channel, final Client client) throws IOException {
SearchRequest searchRequest = new SearchRequest();
RestSearchAction.parseSearchRequest(searchRequest, queryRegistry, request, parseFieldMatcher, aggParsers, null);
RestSearchAction.parseSearchRequest(searchRequest, queryRegistry, request, parseFieldMatcher, aggParsers, suggesters, null);
client.search(searchRequest, new RestStatusToXContentListener<>(channel));
}
@ -103,7 +106,9 @@ public class RestSearchAction extends BaseRestHandler {
* RestAction.hasBodyContent.
*/
public static void parseSearchRequest(SearchRequest searchRequest, IndicesQueriesRegistry indicesQueriesRegistry, RestRequest request,
ParseFieldMatcher parseFieldMatcher, AggregatorParsers aggParsers, BytesReference restContent) throws IOException {
ParseFieldMatcher parseFieldMatcher, AggregatorParsers aggParsers, Suggesters suggesters, BytesReference restContent)
throws IOException {
if (searchRequest.source() == null) {
searchRequest.source(new SearchSourceBuilder());
}
@ -127,7 +132,7 @@ public class RestSearchAction extends BaseRestHandler {
}
} else {
RestActions.parseRestSearchSource(searchRequest.source(), restContent, indicesQueriesRegistry, parseFieldMatcher,
aggParsers);
aggParsers, suggesters);
}
}

View File

@ -24,9 +24,14 @@ import org.elasticsearch.action.suggest.SuggestResponse;
import org.elasticsearch.action.support.IndicesOptions;
import org.elasticsearch.client.Client;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.index.query.QueryParseContext;
import org.elasticsearch.indices.query.IndicesQueriesRegistry;
import org.elasticsearch.rest.BaseRestHandler;
import org.elasticsearch.rest.BytesRestResponse;
import org.elasticsearch.rest.RestChannel;
@ -37,6 +42,10 @@ import org.elasticsearch.rest.RestStatus;
import org.elasticsearch.rest.action.support.RestActions;
import org.elasticsearch.rest.action.support.RestBuilderListener;
import org.elasticsearch.search.suggest.Suggest;
import org.elasticsearch.search.suggest.SuggestBuilder;
import org.elasticsearch.search.suggest.Suggesters;
import java.io.IOException;
import static org.elasticsearch.rest.RestRequest.Method.GET;
import static org.elasticsearch.rest.RestRequest.Method.POST;
@ -47,9 +56,15 @@ import static org.elasticsearch.rest.action.support.RestActions.buildBroadcastSh
*/
public class RestSuggestAction extends BaseRestHandler {
private final IndicesQueriesRegistry queryRegistry;
private final Suggesters suggesters;
@Inject
public RestSuggestAction(Settings settings, RestController controller, Client client) {
public RestSuggestAction(Settings settings, RestController controller, Client client,
IndicesQueriesRegistry queryRegistry, Suggesters suggesters) {
super(settings, client);
this.queryRegistry = queryRegistry;
this.suggesters = suggesters;
controller.registerHandler(POST, "/_suggest", this);
controller.registerHandler(GET, "/_suggest", this);
controller.registerHandler(POST, "/{index}/_suggest", this);
@ -57,11 +72,17 @@ public class RestSuggestAction extends BaseRestHandler {
}
@Override
public void handleRequest(final RestRequest request, final RestChannel channel, final Client client) {
public void handleRequest(final RestRequest request, final RestChannel channel, final Client client) throws IOException {
SuggestRequest suggestRequest = new SuggestRequest(Strings.splitStringByCommaToArray(request.param("index")));
suggestRequest.indicesOptions(IndicesOptions.fromRequest(request, suggestRequest.indicesOptions()));
if (RestActions.hasBodyContent(request)) {
suggestRequest.suggest(RestActions.getRestContent(request));
final BytesReference sourceBytes = RestActions.getRestContent(request);
try (XContentParser parser = XContentFactory.xContent(sourceBytes).createParser(sourceBytes)) {
final QueryParseContext context = new QueryParseContext(queryRegistry);
context.reset(parser);
context.parseFieldMatcher(parseFieldMatcher);
suggestRequest.suggest(SuggestBuilder.fromXContent(context, suggesters));
}
} else {
throw new IllegalArgumentException("no content or source provided to execute suggestion");
}

View File

@ -42,6 +42,7 @@ import org.elasticsearch.indices.query.IndicesQueriesRegistry;
import org.elasticsearch.rest.RestRequest;
import org.elasticsearch.search.aggregations.AggregatorParsers;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.suggest.Suggesters;
import java.io.IOException;
@ -114,14 +115,15 @@ public class RestActions {
return queryBuilder;
}
public static void parseRestSearchSource(SearchSourceBuilder source, BytesReference sourceBytes, IndicesQueriesRegistry queryRegistry,
ParseFieldMatcher parseFieldMatcher, AggregatorParsers aggParsers)
public static void parseRestSearchSource(SearchSourceBuilder source, BytesReference sourceBytes,
IndicesQueriesRegistry queryRegistry, ParseFieldMatcher parseFieldMatcher,
AggregatorParsers aggParsers, Suggesters suggesters)
throws IOException {
XContentParser parser = XContentFactory.xContent(sourceBytes).createParser(sourceBytes);
QueryParseContext queryParseContext = new QueryParseContext(queryRegistry);
queryParseContext.reset(parser);
queryParseContext.parseFieldMatcher(parseFieldMatcher);
source.parseXContent(parser, queryParseContext, aggParsers);
source.parseXContent(parser, queryParseContext, aggParsers, suggesters);
}
/**

View File

@ -228,7 +228,11 @@ import org.elasticsearch.search.suggest.Suggester;
import org.elasticsearch.search.suggest.Suggesters;
import org.elasticsearch.search.suggest.SuggestionBuilder;
import org.elasticsearch.search.suggest.completion.CompletionSuggestionBuilder;
import org.elasticsearch.search.suggest.phrase.Laplace;
import org.elasticsearch.search.suggest.phrase.LinearInterpolation;
import org.elasticsearch.search.suggest.phrase.PhraseSuggestionBuilder;
import org.elasticsearch.search.suggest.phrase.SmoothingModel;
import org.elasticsearch.search.suggest.phrase.StupidBackoff;
import org.elasticsearch.search.suggest.term.TermSuggestionBuilder;
import java.util.ArrayList;
@ -281,8 +285,9 @@ public class SearchModule extends AbstractModule {
highlighters.registerExtension(key, clazz);
}
public void registerSuggester(String key, Class<? extends Suggester> suggester) {
suggesters.registerExtension(key, suggester);
public void registerSuggester(String key, Suggester<?> suggester) {
suggesters.registerExtension(key, suggester.getClass());
namedWriteableRegistry.registerPrototype(SuggestionBuilder.class, suggester.getBuilderPrototype());
}
/**
@ -378,6 +383,9 @@ public class SearchModule extends AbstractModule {
namedWriteableRegistry.registerPrototype(SuggestionBuilder.class, TermSuggestionBuilder.PROTOTYPE);
namedWriteableRegistry.registerPrototype(SuggestionBuilder.class, PhraseSuggestionBuilder.PROTOTYPE);
namedWriteableRegistry.registerPrototype(SuggestionBuilder.class, CompletionSuggestionBuilder.PROTOTYPE);
namedWriteableRegistry.registerPrototype(SmoothingModel.class, Laplace.PROTOTYPE);
namedWriteableRegistry.registerPrototype(SmoothingModel.class, LinearInterpolation.PROTOTYPE);
namedWriteableRegistry.registerPrototype(SmoothingModel.class, StupidBackoff.PROTOTYPE);
}
protected void configureHighlighters() {

View File

@ -55,7 +55,6 @@ import org.elasticsearch.index.search.stats.StatsGroupsParseElement;
import org.elasticsearch.index.shard.IndexEventListener;
import org.elasticsearch.index.shard.IndexShard;
import org.elasticsearch.indices.IndicesService;
import org.elasticsearch.indices.IndicesRequestCache;
import org.elasticsearch.script.ExecutableScript;
import org.elasticsearch.script.ScriptContext;
import org.elasticsearch.script.ScriptService;
@ -92,6 +91,7 @@ import org.elasticsearch.search.query.QuerySearchResultProvider;
import org.elasticsearch.search.query.ScrollQuerySearchResult;
import org.elasticsearch.search.rescore.RescoreBuilder;
import org.elasticsearch.search.searchafter.SearchAfterBuilder;
import org.elasticsearch.search.suggest.Suggesters;
import org.elasticsearch.threadpool.ThreadPool;
import java.io.IOException;
@ -150,14 +150,16 @@ public class SearchService extends AbstractLifecycleComponent<SearchService> imp
private final Map<String, SearchParseElement> elementParsers;
private final ParseFieldMatcher parseFieldMatcher;
private AggregatorParsers aggParsers;
private final AggregatorParsers aggParsers;
private final Suggesters suggesters;
@Inject
public SearchService(Settings settings, ClusterSettings clusterSettings, ClusterService clusterService, IndicesService indicesService,
ThreadPool threadPool, ScriptService scriptService, PageCacheRecycler pageCacheRecycler, BigArrays bigArrays, DfsPhase dfsPhase,
QueryPhase queryPhase, FetchPhase fetchPhase, AggregatorParsers aggParsers) {
ThreadPool threadPool, ScriptService scriptService, PageCacheRecycler pageCacheRecycler, BigArrays bigArrays, DfsPhase dfsPhase,
QueryPhase queryPhase, FetchPhase fetchPhase, AggregatorParsers aggParsers, Suggesters suggesters) {
super(settings);
this.aggParsers = aggParsers;
this.suggesters = suggesters;
this.parseFieldMatcher = new ParseFieldMatcher(settings);
this.threadPool = threadPool;
this.clusterService = clusterService;
@ -555,7 +557,7 @@ public class SearchService extends AbstractLifecycleComponent<SearchService> imp
QueryParseContext queryParseContext = new QueryParseContext(indicesService.getIndicesQueryRegistry());
queryParseContext.reset(parser);
queryParseContext.parseFieldMatcher(parseFieldMatcher);
parseSource(context, SearchSourceBuilder.parseSearchSource(parser, queryParseContext, aggParsers));
parseSource(context, SearchSourceBuilder.parseSearchSource(parser, queryParseContext, aggParsers, suggesters));
}
}
parseSource(context, request.source());
@ -718,20 +720,10 @@ public class SearchService extends AbstractLifecycleComponent<SearchService> imp
}
}
if (source.suggest() != null) {
XContentParser suggestParser = null;
try {
suggestParser = XContentFactory.xContent(source.suggest()).createParser(source.suggest());
suggestParser.nextToken();
this.elementParsers.get("suggest").parse(suggestParser, context);
} catch (Exception e) {
String sSource = "_na_";
try {
sSource = source.toString();
} catch (Throwable e1) {
// ignore
}
XContentLocation location = suggestParser != null ? suggestParser.getTokenLocation() : null;
throw new SearchParseException(context, "failed to parse suggest source [" + sSource + "]", location, e);
context.suggest(source.suggest().build(queryShardContext));
} catch (IOException e) {
throw new SearchContextException(context, "failed to create SuggestionSearchContext", e);
}
}
if (source.rescores() != null) {

View File

@ -55,6 +55,7 @@ import org.elasticsearch.search.sort.SortBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.elasticsearch.search.suggest.SuggestBuilder;
import org.elasticsearch.search.suggest.Suggesters;
import java.io.IOException;
import java.util.ArrayList;
@ -105,9 +106,10 @@ public final class SearchSourceBuilder extends ToXContentToBytes implements Writ
return PROTOTYPE.readFrom(in);
}
public static SearchSourceBuilder parseSearchSource(XContentParser parser, QueryParseContext context, AggregatorParsers aggParsers)
public static SearchSourceBuilder parseSearchSource(XContentParser parser, QueryParseContext context,
AggregatorParsers aggParsers, Suggesters suggesters)
throws IOException {
return PROTOTYPE.fromXContent(parser, context, aggParsers);
return PROTOTYPE.fromXContent(parser, context, aggParsers, suggesters);
}
/**
@ -156,7 +158,7 @@ public final class SearchSourceBuilder extends ToXContentToBytes implements Writ
private HighlightBuilder highlightBuilder;
private BytesReference suggestBuilder;
private SuggestBuilder suggestBuilder;
private BytesReference innerHitsBuilder;
@ -475,20 +477,14 @@ public final class SearchSourceBuilder extends ToXContentToBytes implements Writ
}
public SearchSourceBuilder suggest(SuggestBuilder suggestBuilder) {
try {
XContentBuilder builder = XContentFactory.jsonBuilder();
suggestBuilder.toXContent(builder, EMPTY_PARAMS);
this.suggestBuilder = builder.bytes();
return this;
} catch (IOException e) {
throw new RuntimeException(e);
}
this.suggestBuilder = suggestBuilder;
return this;
}
/**
* Gets the bytes representing the suggester builder for this request.
* Gets the suggester builder for this request.
*/
public BytesReference suggest() {
public SuggestBuilder suggest() {
return suggestBuilder;
}
@ -736,19 +732,22 @@ public final class SearchSourceBuilder extends ToXContentToBytes implements Writ
/**
* Create a new SearchSourceBuilder with attributes set by an xContent.
*/
public SearchSourceBuilder fromXContent(XContentParser parser, QueryParseContext context, AggregatorParsers aggParsers)
public SearchSourceBuilder fromXContent(XContentParser parser, QueryParseContext context,
AggregatorParsers aggParsers, Suggesters suggesters)
throws IOException {
SearchSourceBuilder builder = new SearchSourceBuilder();
builder.parseXContent(parser, context, aggParsers);
builder.parseXContent(parser, context, aggParsers, suggesters);
return builder;
}
/**
* Parse some xContent into this SearchSourceBuilder, overwriting any values specified in the xContent. Use this if you need to set up
* different defaults than a regular SearchSourceBuilder would have and use
* {@link #fromXContent(XContentParser, QueryParseContext, AggregatorParsers)} if you have normal defaults.
* {@link #fromXContent(XContentParser, QueryParseContext, AggregatorParsers, Suggesters)} if you have normal defaults.
*/
public void parseXContent(XContentParser parser, QueryParseContext context, AggregatorParsers aggParsers) throws IOException {
public void parseXContent(XContentParser parser, QueryParseContext context, AggregatorParsers aggParsers, Suggesters suggesters)
throws IOException {
XContentParser.Token token = parser.currentToken();
String currentFieldName = null;
if (token != XContentParser.Token.START_OBJECT && (token = parser.nextToken()) != XContentParser.Token.START_OBJECT) {
@ -852,8 +851,7 @@ public final class SearchSourceBuilder extends ToXContentToBytes implements Writ
XContentBuilder xContentBuilder = XContentFactory.jsonBuilder().copyCurrentStructure(parser);
innerHitsBuilder = xContentBuilder.bytes();
} else if (context.parseFieldMatcher().match(currentFieldName, SUGGEST_FIELD)) {
XContentBuilder xContentBuilder = XContentFactory.jsonBuilder().copyCurrentStructure(parser);
suggestBuilder = xContentBuilder.bytes();
suggestBuilder = SuggestBuilder.fromXContent(context, suggesters);
} else if (context.parseFieldMatcher().match(currentFieldName, SORT_FIELD)) {
sorts = new ArrayList<>();
XContentBuilder xContentBuilder = XContentFactory.jsonBuilder().copyCurrentStructure(parser);
@ -1050,10 +1048,7 @@ public final class SearchSourceBuilder extends ToXContentToBytes implements Writ
}
if (suggestBuilder != null) {
builder.field(SUGGEST_FIELD.getPreferredName());
XContentParser parser = XContentFactory.xContent(XContentType.JSON).createParser(suggestBuilder);
parser.nextToken();
builder.copyCurrentStructure(parser);
builder.field(SUGGEST_FIELD.getPreferredName(), suggestBuilder);
}
if (rescoreBuilders != null) {
@ -1232,7 +1227,7 @@ public final class SearchSourceBuilder extends ToXContentToBytes implements Writ
builder.stats = stats;
}
if (in.readBoolean()) {
builder.suggestBuilder = in.readBytesReference();
builder.suggestBuilder = SuggestBuilder.PROTOTYPE.readFrom(in);
}
builder.terminateAfter = in.readVInt();
builder.timeoutInMillis = in.readLong();
@ -1348,7 +1343,7 @@ public final class SearchSourceBuilder extends ToXContentToBytes implements Writ
boolean hasSuggestBuilder = suggestBuilder != null;
out.writeBoolean(hasSuggestBuilder);
if (hasSuggestBuilder) {
out.writeBytesReference(suggestBuilder);
suggestBuilder.writeTo(out);
}
out.writeVInt(terminateAfter);
out.writeLong(timeoutInMillis);

View File

@ -119,6 +119,10 @@ public class SuggestBuilder extends ToXContentToBytes implements Writeable<Sugge
String fieldName = null;
XContentParser.Token token;
if (parser.currentToken() != XContentParser.Token.START_OBJECT) {
parser.nextToken();
}
assert parser.currentToken() == XContentParser.Token.START_OBJECT;
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
if (token == XContentParser.Token.FIELD_NAME) {
fieldName = parser.currentName();

View File

@ -39,7 +39,7 @@ public abstract class Suggester<T extends SuggestionSearchContext.SuggestionCont
/**
* link the suggester to its corresponding {@link SuggestionBuilder}
*/
public abstract SuggestionBuilder<?> getBuilderPrototype();
public abstract SuggestionBuilder<? extends SuggestionBuilder> getBuilderPrototype();
public Suggest.Suggestion<? extends Suggest.Suggestion.Entry<? extends Suggest.Suggestion.Entry.Option>>
execute(String name, T suggestion, IndexSearcher searcher, CharsRefBuilder spare) throws IOException {

View File

@ -59,7 +59,7 @@ public final class Suggesters extends ExtensionPoint.ClassMap<Suggester> {
return parsers.get(type);
}
public SuggestionBuilder<?> getSuggestionPrototype(String suggesterName) {
public SuggestionBuilder<? extends SuggestionBuilder> getSuggestionPrototype(String suggesterName) {
Suggester<?> suggester = parsers.get(suggesterName);
if (suggester == null) {
throw new IllegalArgumentException("suggester with name [" + suggesterName + "] not supported");

View File

@ -398,9 +398,12 @@ public class TermSuggestionBuilder extends SuggestionBuilder<TermSuggestionBuild
tmpSuggestion.minWordLength(parser.intValue());
} else if (parseFieldMatcher.match(currentFieldName, MIN_DOC_FREQ)) {
tmpSuggestion.minDocFreq(parser.floatValue());
} else {
throw new ParsingException(parser.getTokenLocation(),
"suggester[term] doesn't support field [" + currentFieldName + "]");
}
} else {
throw new ParsingException(parser.getTokenLocation(), "suggester[term] doesn't support field [" + currentFieldName + "]");
throw new ParsingException(parser.getTokenLocation(), "suggester[term] parsing failed on [" + currentFieldName + "]");
}
}

View File

@ -45,7 +45,7 @@ public class MultiSearchRequestTests extends ESTestCase {
IndicesQueriesRegistry registry = new IndicesQueriesRegistry(Settings.EMPTY, singletonMap("match_all", new MatchAllQueryParser()));
byte[] data = StreamsUtils.copyToBytesFromClasspath("/org/elasticsearch/action/search/simple-msearch1.json");
MultiSearchRequest request = RestMultiSearchAction.parseRequest(new MultiSearchRequest(), new BytesArray(data), false, null, null,
null, null, IndicesOptions.strictExpandOpenAndForbidClosed(), true, registry, ParseFieldMatcher.EMPTY, null);
null, null, IndicesOptions.strictExpandOpenAndForbidClosed(), true, registry, ParseFieldMatcher.EMPTY, null, null);
assertThat(request.requests().size(), equalTo(8));
assertThat(request.requests().get(0).indices()[0], equalTo("test"));
assertThat(request.requests().get(0).indicesOptions(), equalTo(IndicesOptions.fromOptions(true, true, true, true, IndicesOptions.strictExpandOpenAndForbidClosed())));
@ -72,7 +72,7 @@ public class MultiSearchRequestTests extends ESTestCase {
IndicesQueriesRegistry registry = new IndicesQueriesRegistry(Settings.EMPTY, singletonMap("match_all", new MatchAllQueryParser()));
byte[] data = StreamsUtils.copyToBytesFromClasspath("/org/elasticsearch/action/search/simple-msearch2.json");
MultiSearchRequest request = RestMultiSearchAction.parseRequest(new MultiSearchRequest(), new BytesArray(data), false, null, null,
null, null, IndicesOptions.strictExpandOpenAndForbidClosed(), true, registry, ParseFieldMatcher.EMPTY, null);
null, null, IndicesOptions.strictExpandOpenAndForbidClosed(), true, registry, ParseFieldMatcher.EMPTY, null, null);
assertThat(request.requests().size(), equalTo(5));
assertThat(request.requests().get(0).indices()[0], equalTo("test"));
assertThat(request.requests().get(0).types().length, equalTo(0));
@ -91,7 +91,7 @@ public class MultiSearchRequestTests extends ESTestCase {
IndicesQueriesRegistry registry = new IndicesQueriesRegistry(Settings.EMPTY, singletonMap("match_all", new MatchAllQueryParser()));
byte[] data = StreamsUtils.copyToBytesFromClasspath("/org/elasticsearch/action/search/simple-msearch3.json");
MultiSearchRequest request = RestMultiSearchAction.parseRequest(new MultiSearchRequest(), new BytesArray(data), false, null, null,
null, null, IndicesOptions.strictExpandOpenAndForbidClosed(), true, registry, ParseFieldMatcher.EMPTY, null);
null, null, IndicesOptions.strictExpandOpenAndForbidClosed(), true, registry, ParseFieldMatcher.EMPTY, null, null);
assertThat(request.requests().size(), equalTo(4));
assertThat(request.requests().get(0).indices()[0], equalTo("test0"));
assertThat(request.requests().get(0).indices()[1], equalTo("test1"));
@ -111,7 +111,7 @@ public class MultiSearchRequestTests extends ESTestCase {
IndicesQueriesRegistry registry = new IndicesQueriesRegistry(Settings.EMPTY, singletonMap("match_all", new MatchAllQueryParser()));
byte[] data = StreamsUtils.copyToBytesFromClasspath("/org/elasticsearch/action/search/simple-msearch4.json");
MultiSearchRequest request = RestMultiSearchAction.parseRequest(new MultiSearchRequest(), new BytesArray(data), false, null, null,
null, null, IndicesOptions.strictExpandOpenAndForbidClosed(), true, registry, ParseFieldMatcher.EMPTY, null);
null, null, IndicesOptions.strictExpandOpenAndForbidClosed(), true, registry, ParseFieldMatcher.EMPTY, null, null);
assertThat(request.requests().size(), equalTo(3));
assertThat(request.requests().get(0).indices()[0], equalTo("test0"));
assertThat(request.requests().get(0).indices()[1], equalTo("test1"));
@ -133,7 +133,7 @@ public class MultiSearchRequestTests extends ESTestCase {
IndicesQueriesRegistry registry = new IndicesQueriesRegistry(Settings.EMPTY, singletonMap("match_all", new MatchAllQueryParser()));
byte[] data = StreamsUtils.copyToBytesFromClasspath("/org/elasticsearch/action/search/simple-msearch5.json");
MultiSearchRequest request = RestMultiSearchAction.parseRequest(new MultiSearchRequest(), new BytesArray(data), true, null, null,
null, null, IndicesOptions.strictExpandOpenAndForbidClosed(), true, registry, ParseFieldMatcher.EMPTY, null);
null, null, IndicesOptions.strictExpandOpenAndForbidClosed(), true, registry, ParseFieldMatcher.EMPTY, null, null);
assertThat(request.requests().size(), equalTo(3));
assertThat(request.requests().get(0).indices()[0], equalTo("test0"));
assertThat(request.requests().get(0).indices()[1], equalTo("test1"));

View File

@ -48,7 +48,7 @@ public class SearchModuleTests extends ModuleTestCase {
}
try {
module.registerSuggester("term", PhraseSuggester.class);
module.registerSuggester("term", PhraseSuggester.PROTOTYPE);
} catch (IllegalArgumentException e) {
assertEquals(e.getMessage(), "Can't register the same [suggester] more than once for [term]");
}
@ -56,9 +56,9 @@ public class SearchModuleTests extends ModuleTestCase {
public void testRegisterSuggester() {
SearchModule module = new SearchModule(Settings.EMPTY, new NamedWriteableRegistry());
module.registerSuggester("custom", CustomSuggester.class);
module.registerSuggester("custom", CustomSuggester.PROTOTYPE);
try {
module.registerSuggester("custom", CustomSuggester.class);
module.registerSuggester("custom", CustomSuggester.PROTOTYPE);
} catch (IllegalArgumentException e) {
assertEquals(e.getMessage(), "Can't register the same [suggester] more than once for [custom]");
}

View File

@ -76,8 +76,8 @@ import org.elasticsearch.search.rescore.QueryRescoreBuilderTests;
import org.elasticsearch.search.searchafter.SearchAfterBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.elasticsearch.search.suggest.SuggestBuilder;
import org.elasticsearch.search.suggest.SuggestBuilders;
import org.elasticsearch.search.suggest.SuggestBuilderTests;
import org.elasticsearch.search.suggest.Suggesters;
import org.elasticsearch.test.ESTestCase;
import org.elasticsearch.test.IndexSettingsModule;
import org.elasticsearch.test.InternalSettingsPlugin;
@ -109,6 +109,8 @@ public class SearchSourceBuilderTests extends ESTestCase {
private static AggregatorParsers aggParsers;
private static Suggesters suggesters;
private static String[] currentTypes;
private static ParseFieldMatcher parseFieldMatcher;
@ -166,7 +168,6 @@ public class SearchSourceBuilderTests extends ESTestCase {
new EnvironmentModule(new Environment(settings)), settingsModule,
new ThreadPoolModule(new ThreadPool(settings)),
scriptModule, new IndicesModule() {
@Override
protected void configure() {
bindMapperExtension();
@ -176,13 +177,8 @@ public class SearchSourceBuilderTests extends ESTestCase {
protected void configureSearch() {
// Skip me
}
@Override
protected void configureSuggesters() {
// Skip me
}
},
new IndexSettingsModule(index, settings),
new AbstractModule() {
@Override
protected void configure() {
@ -193,6 +189,7 @@ public class SearchSourceBuilderTests extends ESTestCase {
}
).createInjector();
aggParsers = injector.getInstance(AggregatorParsers.class);
suggesters = injector.getInstance(Suggesters.class);
// create some random type with some default field, those types will
// stick around for all of the subclasses
currentTypes = new String[randomIntBetween(0, 5)];
@ -409,10 +406,7 @@ public class SearchSourceBuilderTests extends ESTestCase {
builder.highlighter(HighlightBuilderTests.randomHighlighterBuilder());
}
if (randomBoolean()) {
// NORELEASE need a random suggest builder method
builder.suggest(new SuggestBuilder().setGlobalText(randomAsciiOfLengthBetween(1, 5)).addSuggestion(
randomAsciiOfLengthBetween(1, 5),
SuggestBuilders.termSuggestion(randomAsciiOfLengthBetween(1, 5))));
builder.suggest(SuggestBuilderTests.randomSuggestBuilder());
}
if (randomBoolean()) {
// NORELEASE need a random inner hits builder method
@ -460,7 +454,7 @@ public class SearchSourceBuilderTests extends ESTestCase {
if (randomBoolean()) {
parser.nextToken(); // sometimes we move it on the START_OBJECT to test the embedded case
}
SearchSourceBuilder newBuilder = SearchSourceBuilder.parseSearchSource(parser, parseContext, aggParsers);
SearchSourceBuilder newBuilder = SearchSourceBuilder.parseSearchSource(parser, parseContext, aggParsers, suggesters);
assertNull(parser.nextToken());
assertEquals(testBuilder, newBuilder);
assertEquals(testBuilder.hashCode(), newBuilder.hashCode());
@ -498,14 +492,17 @@ public class SearchSourceBuilderTests extends ESTestCase {
assertTrue("source builder is not equal to self", secondBuilder.equals(secondBuilder));
assertTrue("source builder is not equal to its copy", firstBuilder.equals(secondBuilder));
assertTrue("source builder is not symmetric", secondBuilder.equals(firstBuilder));
assertThat("source builder copy's hashcode is different from original hashcode", secondBuilder.hashCode(), equalTo(firstBuilder.hashCode()));
assertThat("source builder copy's hashcode is different from original hashcode",
secondBuilder.hashCode(), equalTo(firstBuilder.hashCode()));
SearchSourceBuilder thirdBuilder = copyBuilder(secondBuilder);
assertTrue("source builder is not equal to self", thirdBuilder.equals(thirdBuilder));
assertTrue("source builder is not equal to its copy", secondBuilder.equals(thirdBuilder));
assertThat("source builder copy's hashcode is different from original hashcode", secondBuilder.hashCode(), equalTo(thirdBuilder.hashCode()));
assertThat("source builder copy's hashcode is different from original hashcode",
secondBuilder.hashCode(), equalTo(thirdBuilder.hashCode()));
assertTrue("equals is not transitive", firstBuilder.equals(thirdBuilder));
assertThat("source builder copy's hashcode is different from original hashcode", firstBuilder.hashCode(), equalTo(thirdBuilder.hashCode()));
assertThat("source builder copy's hashcode is different from original hashcode",
firstBuilder.hashCode(), equalTo(thirdBuilder.hashCode()));
assertTrue("equals is not symmetric", thirdBuilder.equals(secondBuilder));
assertTrue("equals is not symmetric", thirdBuilder.equals(firstBuilder));
}
@ -525,7 +522,7 @@ public class SearchSourceBuilderTests extends ESTestCase {
String restContent = " { \"_source\": { \"includes\": \"include\", \"excludes\": \"*.field2\"}}";
try (XContentParser parser = XContentFactory.xContent(restContent).createParser(restContent)) {
SearchSourceBuilder searchSourceBuilder = SearchSourceBuilder.parseSearchSource(parser, createParseContext(parser),
aggParsers);
aggParsers, suggesters);
assertArrayEquals(new String[]{"*.field2" }, searchSourceBuilder.fetchSource().excludes());
assertArrayEquals(new String[]{"include" }, searchSourceBuilder.fetchSource().includes());
}
@ -534,7 +531,7 @@ public class SearchSourceBuilderTests extends ESTestCase {
String restContent = " { \"_source\": false}";
try (XContentParser parser = XContentFactory.xContent(restContent).createParser(restContent)) {
SearchSourceBuilder searchSourceBuilder = SearchSourceBuilder.parseSearchSource(parser, createParseContext(parser),
aggParsers);
aggParsers, suggesters);
assertArrayEquals(new String[]{}, searchSourceBuilder.fetchSource().excludes());
assertArrayEquals(new String[]{}, searchSourceBuilder.fetchSource().includes());
assertFalse(searchSourceBuilder.fetchSource().fetchSource());
@ -547,7 +544,7 @@ public class SearchSourceBuilderTests extends ESTestCase {
String restContent = " { \"sort\": \"foo\"}";
try (XContentParser parser = XContentFactory.xContent(restContent).createParser(restContent)) {
SearchSourceBuilder searchSourceBuilder = SearchSourceBuilder.parseSearchSource(parser, createParseContext(parser),
aggParsers);
aggParsers, suggesters);
assertEquals(1, searchSourceBuilder.sorts().size());
assertEquals("{\"foo\":{\"order\":\"asc\"}}", searchSourceBuilder.sorts().get(0).toUtf8());
}
@ -563,7 +560,7 @@ public class SearchSourceBuilderTests extends ESTestCase {
" ]}";
try (XContentParser parser = XContentFactory.xContent(restContent).createParser(restContent)) {
SearchSourceBuilder searchSourceBuilder = SearchSourceBuilder.parseSearchSource(parser, createParseContext(parser),
aggParsers);
aggParsers, suggesters);
assertEquals(5, searchSourceBuilder.sorts().size());
assertEquals("{\"post_date\":{\"order\":\"asc\"}}", searchSourceBuilder.sorts().get(0).toUtf8());
assertEquals("\"user\"", searchSourceBuilder.sorts().get(1).toUtf8());

View File

@ -46,6 +46,7 @@ import org.elasticsearch.index.mapper.core.StringFieldMapper.StringFieldType;
import org.elasticsearch.index.query.QueryParseContext;
import org.elasticsearch.index.query.QueryShardContext;
import org.elasticsearch.indices.IndicesModule;
import org.elasticsearch.indices.query.IndicesQueriesRegistry;
import org.elasticsearch.script.CompiledScript;
import org.elasticsearch.script.Script;
import org.elasticsearch.script.ScriptContext;
@ -54,6 +55,7 @@ import org.elasticsearch.script.ScriptEngineRegistry;
import org.elasticsearch.script.ScriptService;
import org.elasticsearch.script.ScriptServiceTests.TestEngineService;
import org.elasticsearch.script.ScriptSettings;
import org.elasticsearch.search.SearchModule;
import org.elasticsearch.search.suggest.SuggestionSearchContext.SuggestionContext;
import org.elasticsearch.search.suggest.completion.CompletionSuggestionBuilder;
import org.elasticsearch.search.suggest.phrase.PhraseSuggestionBuilder;
@ -78,7 +80,9 @@ public abstract class AbstractSuggestionBuilderTestCase<SB extends SuggestionBui
private static final int NUMBER_OF_TESTBUILDERS = 20;
protected static NamedWriteableRegistry namedWriteableRegistry;
private static Suggesters suggesters;
protected static IndicesQueriesRegistry queriesRegistry;
protected static ParseFieldMatcher parseFieldMatcher;
protected static Suggesters suggesters;
private static ScriptService scriptService;
private static SuggestParseElement parseElement;
@ -111,11 +115,15 @@ public abstract class AbstractSuggestionBuilderTestCase<SB extends SuggestionBui
namedWriteableRegistry.registerPrototype(SuggestionBuilder.class, TermSuggestionBuilder.PROTOTYPE);
namedWriteableRegistry.registerPrototype(SuggestionBuilder.class, PhraseSuggestionBuilder.PROTOTYPE);
namedWriteableRegistry.registerPrototype(SuggestionBuilder.class, CompletionSuggestionBuilder.PROTOTYPE);
queriesRegistry = new SearchModule(Settings.EMPTY, namedWriteableRegistry).buildQueryParserRegistry();
parseFieldMatcher = ParseFieldMatcher.STRICT;
}
@AfterClass
public static void afterClass() throws Exception {
namedWriteableRegistry = null;
suggesters = null;
queriesRegistry = null;
}
/**
@ -136,13 +144,16 @@ public abstract class AbstractSuggestionBuilderTestCase<SB extends SuggestionBui
*/
protected SB randomTestBuilder() {
SB randomSuggestion = randomSuggestionBuilder();
maybeSet(randomSuggestion::text, randomAsciiOfLengthBetween(2, 20));
return randomSuggestion;
}
public static void setCommonPropertiesOnRandomBuilder(SuggestionBuilder<?> randomSuggestion) {
randomSuggestion.text(randomAsciiOfLengthBetween(2, 20)); // have to set the text because we don't know if the global text was set
maybeSet(randomSuggestion::prefix, randomAsciiOfLengthBetween(2, 20));
maybeSet(randomSuggestion::regex, randomAsciiOfLengthBetween(2, 20));
maybeSet(randomSuggestion::analyzer, randomAsciiOfLengthBetween(2, 20));
maybeSet(randomSuggestion::size, randomIntBetween(1, 20));
maybeSet(randomSuggestion::shardSize, randomIntBetween(1, 20));
return randomSuggestion;
}
/**
@ -357,4 +368,11 @@ public abstract class AbstractSuggestionBuilderTestCase<SB extends SuggestionBui
}
}
}
protected static QueryParseContext newParseContext(final String xcontent) throws IOException {
final QueryParseContext parseContext = new QueryParseContext(queriesRegistry);
parseContext.reset(XContentFactory.xContent(xcontent).createParser(xcontent));
parseContext.parseFieldMatcher(parseFieldMatcher);
return parseContext;
}
}

View File

@ -24,7 +24,6 @@ import com.carrotsearch.randomizedtesting.generators.RandomStrings;
import org.apache.lucene.analysis.TokenStreamToAutomaton;
import org.apache.lucene.search.suggest.document.ContextSuggestField;
import org.apache.lucene.util.LuceneTestCase.SuppressCodecs;
import org.elasticsearch.action.ShardOperationFailedException;
import org.elasticsearch.action.admin.indices.forcemerge.ForceMergeResponse;
import org.elasticsearch.action.admin.indices.mapping.put.PutMappingResponse;
import org.elasticsearch.action.admin.indices.segments.IndexShardSegments;
@ -33,7 +32,6 @@ import org.elasticsearch.action.admin.indices.stats.IndicesStatsResponse;
import org.elasticsearch.action.index.IndexRequestBuilder;
import org.elasticsearch.action.percolate.PercolateResponse;
import org.elasticsearch.action.search.SearchPhaseExecutionException;
import org.elasticsearch.action.suggest.SuggestRequest;
import org.elasticsearch.action.suggest.SuggestResponse;
import org.elasticsearch.client.Requests;
import org.elasticsearch.common.settings.Settings;
@ -211,32 +209,6 @@ public class CompletionSuggestSearchIT extends ESIntegTestCase {
}
}
public void testMalformedRequestPayload() throws Exception {
final CompletionMappingBuilder mapping = new CompletionMappingBuilder();
createIndexAndMapping(mapping);
SuggestRequest request = new SuggestRequest(INDEX);
XContentBuilder suggest = jsonBuilder().startObject()
.startObject("bad-payload")
.field("prefix", "sug")
.startObject("completion")
.field("field", FIELD)
.startArray("payload")
.startObject()
.field("payload", "field")
.endObject()
.endArray()
.endObject()
.endObject().endObject();
request.suggest(suggest.bytes());
ensureGreen();
SuggestResponse suggestResponse = client().suggest(request).get();
assertThat(suggestResponse.getSuccessfulShards(), equalTo(0));
for (ShardOperationFailedException exception : suggestResponse.getShardFailures()) {
assertThat(exception.reason(), containsString("ParsingException[[completion] failed to parse field [payload]]; nested: IllegalStateException[Can't get text on a START_OBJECT"));
}
}
public void testMissingPayloadField() throws Exception {
final CompletionMappingBuilder mapping = new CompletionMappingBuilder();
createIndexAndMapping(mapping);

View File

@ -32,6 +32,7 @@ import java.util.Map;
*/
public class CustomSuggester extends Suggester<CustomSuggester.CustomSuggestionsContext> {
public static CustomSuggester PROTOTYPE = new CustomSuggester();
// This is a pretty dumb implementation which returns the original text + fieldName + custom config option + 12 or 123
@Override

View File

@ -37,7 +37,7 @@ public class CustomSuggesterPlugin extends Plugin {
}
public void onModule(SearchModule searchModule) {
searchModule.registerSuggester("custom", CustomSuggester.class);
searchModule.registerSuggester("custom", CustomSuggester.PROTOTYPE);
}
}

View File

@ -20,10 +20,15 @@ package org.elasticsearch.search.suggest;
import org.elasticsearch.action.search.SearchRequestBuilder;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.common.ParseField;
import org.elasticsearch.common.ParseFieldMatcher;
import org.elasticsearch.common.ParsingException;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.lucene.BytesRefs;
import org.elasticsearch.common.util.CollectionUtils;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.index.query.QueryParseContext;
import org.elasticsearch.index.query.QueryShardContext;
import org.elasticsearch.plugins.Plugin;
@ -75,16 +80,20 @@ public class CustomSuggesterSearchIT extends ESIntegTestCase {
// TODO: infer type once JI-9019884 is fixed
// TODO: see also JDK-8039214
List<Suggest.Suggestion.Entry<? extends Suggest.Suggestion.Entry.Option>> suggestions
= CollectionUtils.<Suggest.Suggestion.Entry<? extends Suggest.Suggestion.Entry.Option>>iterableAsArrayList(searchResponse.getSuggest().getSuggestion("someName"));
List<Suggest.Suggestion.Entry<? extends Suggest.Suggestion.Entry.Option>> suggestions =
CollectionUtils.<Suggest.Suggestion.Entry<? extends Suggest.Suggestion.Entry.Option>>iterableAsArrayList(
searchResponse.getSuggest().getSuggestion("someName"));
assertThat(suggestions, hasSize(2));
assertThat(suggestions.get(0).getText().string(), is(String.format(Locale.ROOT, "%s-%s-%s-12", randomText, randomField, randomSuffix)));
assertThat(suggestions.get(1).getText().string(), is(String.format(Locale.ROOT, "%s-%s-%s-123", randomText, randomField, randomSuffix)));
assertThat(suggestions.get(0).getText().string(),
is(String.format(Locale.ROOT, "%s-%s-%s-12", randomText, randomField, randomSuffix)));
assertThat(suggestions.get(1).getText().string(),
is(String.format(Locale.ROOT, "%s-%s-%s-123", randomText, randomField, randomSuffix)));
}
static class CustomSuggestionBuilder extends SuggestionBuilder<CustomSuggestionBuilder> {
public static class CustomSuggestionBuilder extends SuggestionBuilder<CustomSuggestionBuilder> {
public final static CustomSuggestionBuilder PROTOTYPE = new CustomSuggestionBuilder("_na_", "_na_");
protected static final ParseField RANDOM_SUFFIX_FIELD = new ParseField("suffix");
private String randomSuffix;
@ -95,7 +104,7 @@ public class CustomSuggesterSearchIT extends ESIntegTestCase {
@Override
protected XContentBuilder innerToXContent(XContentBuilder builder, Params params) throws IOException {
builder.field("suffix", randomSuffix);
builder.field(RANDOM_SUFFIX_FIELD.getPreferredName(), randomSuffix);
return builder;
}
@ -125,19 +134,64 @@ public class CustomSuggesterSearchIT extends ESIntegTestCase {
}
@Override
protected CustomSuggestionBuilder innerFromXContent(QueryParseContext parseContext)
throws IOException {
// TODO some parsing
return new CustomSuggestionBuilder(field(), randomSuffix);
protected CustomSuggestionBuilder innerFromXContent(QueryParseContext parseContext) throws IOException {
XContentParser parser = parseContext.parser();
ParseFieldMatcher parseFieldMatcher = parseContext.parseFieldMatcher();
XContentParser.Token token;
String currentFieldName = null;
String fieldname = null;
String suffix = null;
String analyzer = null;
int sizeField = -1;
int shardSize = -1;
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
if (token == XContentParser.Token.FIELD_NAME) {
currentFieldName = parser.currentName();
} else if (token.isValue()) {
if (parseFieldMatcher.match(currentFieldName, SuggestionBuilder.ANALYZER_FIELD)) {
analyzer = parser.text();
} else if (parseFieldMatcher.match(currentFieldName, SuggestionBuilder.FIELDNAME_FIELD)) {
fieldname = parser.text();
} else if (parseFieldMatcher.match(currentFieldName, SuggestionBuilder.SIZE_FIELD)) {
sizeField = parser.intValue();
} else if (parseFieldMatcher.match(currentFieldName, SuggestionBuilder.SHARDSIZE_FIELD)) {
shardSize = parser.intValue();
} else if (parseFieldMatcher.match(currentFieldName, RANDOM_SUFFIX_FIELD)) {
suffix = parser.text();
}
} else {
throw new ParsingException(parser.getTokenLocation(),
"suggester[custom] doesn't support field [" + currentFieldName + "]");
}
}
// now we should have field name, check and copy fields over to the suggestion builder we return
if (fieldname == null) {
throw new ParsingException(parser.getTokenLocation(), "the required field option is missing");
}
CustomSuggestionBuilder builder = new CustomSuggestionBuilder(fieldname, suffix);
if (analyzer != null) {
builder.analyzer(analyzer);
}
if (sizeField != -1) {
builder.size(sizeField);
}
if (shardSize != -1) {
builder.shardSize(shardSize);
}
return builder;
}
@Override
protected SuggestionContext innerBuild(QueryShardContext context) throws IOException {
Map<String, Object> options = new HashMap<>();
options.put("field", field());
options.put("suffix", randomSuffix);
CustomSuggester.CustomSuggestionsContext customSuggestionsContext = new CustomSuggester.CustomSuggestionsContext(context, options);
options.put(FIELDNAME_FIELD.getPreferredName(), field());
options.put(RANDOM_SUFFIX_FIELD.getPreferredName(), randomSuffix);
CustomSuggester.CustomSuggestionsContext customSuggestionsContext =
new CustomSuggester.CustomSuggestionsContext(context, options);
customSuggestionsContext.setField(field());
assert text != null;
customSuggestionsContext.setText(BytesRefs.toBytesRef(text));
return customSuggestionsContext;
}

View File

@ -30,6 +30,7 @@ import org.elasticsearch.common.xcontent.XContentHelper;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.QueryParseContext;
import org.elasticsearch.search.suggest.completion.CompletionSuggesterBuilderTests;
import org.elasticsearch.search.suggest.completion.CompletionSuggestionBuilder;
import org.elasticsearch.search.suggest.completion.WritableTestCase;
import org.elasticsearch.search.suggest.phrase.Laplace;
@ -39,6 +40,9 @@ import org.elasticsearch.search.suggest.phrase.PhraseSuggestionBuilderTests;
import org.elasticsearch.search.suggest.phrase.SmoothingModel;
import org.elasticsearch.search.suggest.phrase.StupidBackoff;
import org.elasticsearch.search.suggest.term.TermSuggestionBuilder;
import org.elasticsearch.search.suggest.term.TermSuggestionBuilderTests;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import java.io.IOException;
import java.util.Collections;
@ -46,16 +50,30 @@ import java.util.Map.Entry;
public class SuggestBuilderTests extends WritableTestCase<SuggestBuilder> {
private static NamedWriteableRegistry namedWriteableRegistry;
/**
* Setup for the whole base test class.
*/
@BeforeClass
public static void init() {
NamedWriteableRegistry nwRegistry = new NamedWriteableRegistry();
nwRegistry.registerPrototype(SuggestionBuilder.class, TermSuggestionBuilder.PROTOTYPE);
nwRegistry.registerPrototype(SuggestionBuilder.class, PhraseSuggestionBuilder.PROTOTYPE);
nwRegistry.registerPrototype(SuggestionBuilder.class, CompletionSuggestionBuilder.PROTOTYPE);
nwRegistry.registerPrototype(SmoothingModel.class, Laplace.PROTOTYPE);
nwRegistry.registerPrototype(SmoothingModel.class, LinearInterpolation.PROTOTYPE);
nwRegistry.registerPrototype(SmoothingModel.class, StupidBackoff.PROTOTYPE);
namedWriteableRegistry = nwRegistry;
}
@AfterClass
public static void afterClass() {
namedWriteableRegistry = null;
}
@Override
protected NamedWriteableRegistry provideNamedWritableRegistry() {
NamedWriteableRegistry namedWriteableRegistry = new NamedWriteableRegistry();
namedWriteableRegistry.registerPrototype(SuggestionBuilder.class, TermSuggestionBuilder.PROTOTYPE);
namedWriteableRegistry.registerPrototype(SuggestionBuilder.class, PhraseSuggestionBuilder.PROTOTYPE);
namedWriteableRegistry.registerPrototype(SuggestionBuilder.class, CompletionSuggestionBuilder.PROTOTYPE);
namedWriteableRegistry.registerPrototype(SmoothingModel.class, Laplace.PROTOTYPE);
namedWriteableRegistry.registerPrototype(SmoothingModel.class, LinearInterpolation.PROTOTYPE);
namedWriteableRegistry.registerPrototype(SmoothingModel.class, StupidBackoff.PROTOTYPE);
return namedWriteableRegistry;
}
@ -75,7 +93,6 @@ public class SuggestBuilderTests extends WritableTestCase<SuggestBuilder> {
suggestBuilder.toXContent(xContentBuilder, ToXContent.EMPTY_PARAMS);
XContentParser parser = XContentHelper.createParser(xContentBuilder.bytes());
context.reset(parser);
parser.nextToken();
SuggestBuilder secondSuggestBuilder = SuggestBuilder.fromXContent(context, suggesters);
assertNotSame(suggestBuilder, secondSuggestBuilder);
@ -84,17 +101,26 @@ public class SuggestBuilderTests extends WritableTestCase<SuggestBuilder> {
}
}
public void testIllegalSuggestionName() {
try {
new SuggestBuilder().addSuggestion(null, PhraseSuggestionBuilderTests.randomPhraseSuggestionBuilder());
fail("exception expected");
} catch (NullPointerException e) {
assertEquals("every suggestion needs a name", e.getMessage());
}
try {
new SuggestBuilder().addSuggestion("my-suggest", PhraseSuggestionBuilderTests.randomPhraseSuggestionBuilder())
.addSuggestion("my-suggest", PhraseSuggestionBuilderTests.randomPhraseSuggestionBuilder());
fail("exception expected");
} catch (IllegalArgumentException e) {
assertEquals("already added another suggestion with name [my-suggest]", e.getMessage());
}
}
@Override
protected SuggestBuilder createTestModel() {
SuggestBuilder suggestBuilder = new SuggestBuilder();
if (randomBoolean()) {
suggestBuilder.setGlobalText(randomAsciiOfLengthBetween(5, 50));
}
int numberOfSuggestions = randomIntBetween(0, 5);
for (int i = 0; i < numberOfSuggestions; i++) {
suggestBuilder.addSuggestion(randomAsciiOfLength(10), PhraseSuggestionBuilderTests.randomPhraseSuggestionBuilder());
}
return suggestBuilder;
return randomSuggestBuilder();
}
@Override
@ -111,26 +137,30 @@ public class SuggestBuilderTests extends WritableTestCase<SuggestBuilder> {
return mutation;
}
public void testIllegalSuggestionName() {
try {
new SuggestBuilder().addSuggestion(null, PhraseSuggestionBuilderTests.randomPhraseSuggestionBuilder());
fail("exception expected");
} catch (NullPointerException e) {
assertEquals("every suggestion needs a name", e.getMessage());
}
try {
new SuggestBuilder().addSuggestion("my-suggest", PhraseSuggestionBuilderTests.randomPhraseSuggestionBuilder())
.addSuggestion("my-suggest", PhraseSuggestionBuilderTests.randomPhraseSuggestionBuilder());
fail("exception expected");
} catch (IllegalArgumentException e) {
assertEquals("already added another suggestion with name [my-suggest]", e.getMessage());
}
}
@Override
protected SuggestBuilder readFrom(StreamInput in) throws IOException {
return SuggestBuilder.PROTOTYPE.readFrom(in);
}
public static SuggestBuilder randomSuggestBuilder() {
SuggestBuilder builder = new SuggestBuilder();
if (randomBoolean()) {
builder.setGlobalText(randomAsciiOfLengthBetween(1, 20));
}
final int numSuggestions = randomIntBetween(1, 5);
for (int i = 0; i < numSuggestions; i++) {
builder.addSuggestion(randomAsciiOfLengthBetween(5, 10), randomSuggestionBuilder());
}
return builder;
}
private static SuggestionBuilder<?> randomSuggestionBuilder() {
switch (randomIntBetween(0, 2)) {
case 0: return TermSuggestionBuilderTests.randomTermSuggestionBuilder();
case 1: return PhraseSuggestionBuilderTests.randomPhraseSuggestionBuilder();
case 2: return CompletionSuggesterBuilderTests.randomCompletionSuggestionBuilder();
default: return TermSuggestionBuilderTests.randomTermSuggestionBuilder();
}
}
}

View File

@ -19,15 +19,14 @@
package org.elasticsearch.search.suggest.completion;
import com.carrotsearch.randomizedtesting.generators.RandomStrings;
import org.elasticsearch.common.ParsingException;
import org.elasticsearch.common.collect.Tuple;
import org.elasticsearch.common.unit.Fuzziness;
import org.elasticsearch.index.IndexSettings;
import org.elasticsearch.index.analysis.AnalysisService;
import org.elasticsearch.index.mapper.MappedFieldType;
import org.elasticsearch.index.mapper.MapperService;
import org.elasticsearch.index.mapper.core.CompletionFieldMapper;
import org.elasticsearch.indices.IndicesModule;
import org.elasticsearch.search.suggest.AbstractSuggestionBuilderTestCase;
import org.elasticsearch.search.suggest.SuggestBuilder;
import org.elasticsearch.search.suggest.SuggestionSearchContext.SuggestionContext;
import org.elasticsearch.search.suggest.completion.context.CategoryContextMapping;
import org.elasticsearch.search.suggest.completion.context.CategoryQueryContext;
@ -36,22 +35,27 @@ import org.elasticsearch.search.suggest.completion.context.ContextMappings;
import org.elasticsearch.search.suggest.completion.context.GeoContextMapping;
import org.elasticsearch.search.suggest.completion.context.GeoQueryContext;
import org.elasticsearch.search.suggest.completion.context.QueryContext;
import org.junit.BeforeClass;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.stream.Collectors;
import static org.hamcrest.core.IsInstanceOf.instanceOf;
import static org.hamcrest.Matchers.containsString;
public class CompletionSuggesterBuilderTests extends AbstractSuggestionBuilderTestCase<CompletionSuggestionBuilder> {
@Override
protected CompletionSuggestionBuilder randomSuggestionBuilder() {
return randomCompletionSuggestionBuilder();
}
public static CompletionSuggestionBuilder randomCompletionSuggestionBuilder() {
return randomSuggestionBuilderWithContextInfo().builder;
}
@ -61,9 +65,10 @@ public class CompletionSuggesterBuilderTests extends AbstractSuggestionBuilderTe
List<String> geoContexts = new ArrayList<>();
}
private BuilderAndInfo randomSuggestionBuilderWithContextInfo() {
private static BuilderAndInfo randomSuggestionBuilderWithContextInfo() {
final BuilderAndInfo builderAndInfo = new BuilderAndInfo();
CompletionSuggestionBuilder testBuilder = new CompletionSuggestionBuilder(randomAsciiOfLengthBetween(2, 20));
setCommonPropertiesOnRandomBuilder(testBuilder);
switch (randomIntBetween(0, 3)) {
case 0:
testBuilder.prefix(randomAsciiOfLength(10));
@ -172,4 +177,26 @@ public class CompletionSuggesterBuilderTests extends AbstractSuggestionBuilderTe
throw new IllegalStateException("should not through");
}
}
/**
* Test that a malformed JSON suggestion request fails.
*/
public void testMalformedJsonRequestPayload() throws Exception {
final String field = RandomStrings.randomAsciiOfLength(getRandom(), 10).toLowerCase(Locale.ROOT);
final String payload = "{\n" +
" \"bad-payload\" : { \n" +
" \"prefix\" : \"sug\",\n" +
" \"completion\" : { \n" +
" \"field\" : \"" + field + "\",\n " +
" \"payload\" : [ {\"payload\":\"field\"} ]\n" +
" }\n" +
" }\n" +
"}\n";
try {
final SuggestBuilder suggestBuilder = SuggestBuilder.fromXContent(newParseContext(payload), suggesters);
fail("Should not have been able to create SuggestBuilder from malformed JSON: " + suggestBuilder);
} catch (ParsingException e) {
assertThat(e.getMessage(), containsString("failed to parse field [payload]"));
}
}
}

View File

@ -48,6 +48,7 @@ public class PhraseSuggestionBuilderTests extends AbstractSuggestionBuilderTestC
public static PhraseSuggestionBuilder randomPhraseSuggestionBuilder() {
PhraseSuggestionBuilder testBuilder = new PhraseSuggestionBuilder(randomAsciiOfLengthBetween(2, 20));
setCommonPropertiesOnRandomBuilder(testBuilder);
maybeSet(testBuilder::maxErrors, randomFloat());
maybeSet(testBuilder::separator, randomAsciiOfLengthBetween(1, 10));
maybeSet(testBuilder::realWordErrorLikelihood, randomFloat());

View File

@ -19,14 +19,17 @@
package org.elasticsearch.search.suggest.term;
import com.carrotsearch.randomizedtesting.generators.RandomStrings;
import org.elasticsearch.search.suggest.AbstractSuggestionBuilderTestCase;
import org.elasticsearch.search.suggest.DirectSpellcheckerSettings;
import org.elasticsearch.search.suggest.SortBy;
import org.elasticsearch.search.suggest.SuggestBuilder;
import org.elasticsearch.search.suggest.SuggestionSearchContext.SuggestionContext;
import org.elasticsearch.search.suggest.term.TermSuggestionBuilder.StringDistanceImpl;
import org.elasticsearch.search.suggest.term.TermSuggestionBuilder.SuggestMode;
import java.io.IOException;
import java.util.Locale;
import static org.elasticsearch.search.suggest.DirectSpellcheckerSettings.DEFAULT_ACCURACY;
import static org.elasticsearch.search.suggest.DirectSpellcheckerSettings.DEFAULT_MAX_EDITS;
@ -35,6 +38,7 @@ import static org.elasticsearch.search.suggest.DirectSpellcheckerSettings.DEFAUL
import static org.elasticsearch.search.suggest.DirectSpellcheckerSettings.DEFAULT_MIN_DOC_FREQ;
import static org.elasticsearch.search.suggest.DirectSpellcheckerSettings.DEFAULT_MIN_WORD_LENGTH;
import static org.elasticsearch.search.suggest.DirectSpellcheckerSettings.DEFAULT_PREFIX_LENGTH;
import static org.hamcrest.Matchers.containsString;
/**
* Test the {@link TermSuggestionBuilder} class.
@ -46,7 +50,15 @@ public class TermSuggestionBuilderTests extends AbstractSuggestionBuilderTestCas
*/
@Override
protected TermSuggestionBuilder randomSuggestionBuilder() {
return randomTermSuggestionBuilder();
}
/**
* Creates a random TermSuggestionBuilder
*/
public static TermSuggestionBuilder randomTermSuggestionBuilder() {
TermSuggestionBuilder testBuilder = new TermSuggestionBuilder(randomAsciiOfLengthBetween(2, 20));
setCommonPropertiesOnRandomBuilder(testBuilder);
maybeSet(testBuilder::suggestMode, randomSuggestMode());
maybeSet(testBuilder::accuracy, randomFloat());
maybeSet(testBuilder::sort, randomSort());
@ -60,7 +72,7 @@ public class TermSuggestionBuilderTests extends AbstractSuggestionBuilderTestCas
return testBuilder;
}
private SuggestMode randomSuggestMode() {
private static SuggestMode randomSuggestMode() {
final int randomVal = randomIntBetween(0, 2);
switch (randomVal) {
case 0: return SuggestMode.MISSING;
@ -70,7 +82,7 @@ public class TermSuggestionBuilderTests extends AbstractSuggestionBuilderTestCas
}
}
private SortBy randomSort() {
private static SortBy randomSort() {
int randomVal = randomIntBetween(0, 1);
switch (randomVal) {
case 0: return SortBy.SCORE;
@ -79,7 +91,7 @@ public class TermSuggestionBuilderTests extends AbstractSuggestionBuilderTestCas
}
}
private StringDistanceImpl randomStringDistance() {
private static StringDistanceImpl randomStringDistance() {
int randomVal = randomIntBetween(0, 4);
switch (randomVal) {
case 0: return StringDistanceImpl.INTERNAL;
@ -272,6 +284,24 @@ public class TermSuggestionBuilderTests extends AbstractSuggestionBuilderTestCas
assertEquals(SuggestMode.MISSING, builder.suggestMode());
}
public void testMalformedJson() {
final String field = RandomStrings.randomAsciiOfLength(getRandom(), 10).toLowerCase(Locale.ROOT);
String suggest = "{\n" +
" \"bad-payload\" : {\n" +
" \"text\" : \"the amsterdma meetpu\",\n" +
" \"term\" : {\n" +
" \"field\" : { \"" + field + "\" : \"bad-object\" }\n" +
" }\n" +
" }\n" +
"}";
try {
final SuggestBuilder suggestBuilder = SuggestBuilder.fromXContent(newParseContext(suggest), suggesters);
fail("Should not have been able to create SuggestBuilder from malformed JSON: " + suggestBuilder);
} catch (Exception e) {
assertThat(e.getMessage(), containsString("parsing failed"));
}
}
@Override
protected void assertSuggestionContext(SuggestionContext oldSuggestion, SuggestionContext newSuggestion) {
@SuppressWarnings("unchecked")

View File

@ -93,6 +93,7 @@ import org.elasticsearch.plugins.Plugin;
import org.elasticsearch.script.Script;
import org.elasticsearch.script.groovy.GroovyPlugin;
import org.elasticsearch.search.action.SearchTransportService;
import org.elasticsearch.search.suggest.SuggestBuilder;
import org.elasticsearch.tasks.Task;
import org.elasticsearch.test.ESIntegTestCase;
import org.elasticsearch.test.ESIntegTestCase.ClusterScope;
@ -445,7 +446,7 @@ public class IndicesRequestTests extends ESIntegTestCase {
String suggestAction = SuggestAction.NAME + "[s]";
interceptTransportActions(suggestAction);
SuggestRequest suggestRequest = new SuggestRequest(randomIndicesOrAliases());
SuggestRequest suggestRequest = new SuggestRequest(randomIndicesOrAliases()).suggest(new SuggestBuilder());
internalCluster().clientNodeClient().suggest(suggestRequest).actionGet();
clearInterceptedActions();

View File

@ -20,6 +20,38 @@
package org.elasticsearch.messy.tests;
import static org.elasticsearch.cluster.metadata.IndexMetaData.SETTING_NUMBER_OF_REPLICAS;
import static org.elasticsearch.cluster.metadata.IndexMetaData.SETTING_NUMBER_OF_SHARDS;
import static org.elasticsearch.common.settings.Settings.settingsBuilder;
import static org.elasticsearch.index.query.QueryBuilders.matchQuery;
import static org.elasticsearch.search.suggest.SuggestBuilders.phraseSuggestion;
import static org.elasticsearch.search.suggest.SuggestBuilders.termSuggestion;
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked;
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertNoFailures;
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertSuggestion;
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertSuggestionPhraseCollateMatchExists;
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertSuggestionSize;
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertThrows;
import static org.hamcrest.Matchers.anyOf;
import static org.hamcrest.Matchers.endsWith;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.Matchers.nullValue;
import java.io.IOException;
import java.net.URISyntaxException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ExecutionException;
import org.elasticsearch.ElasticsearchException;
import org.elasticsearch.action.admin.indices.create.CreateIndexRequestBuilder;
import org.elasticsearch.action.index.IndexRequestBuilder;
@ -49,38 +81,6 @@ import org.elasticsearch.search.suggest.term.TermSuggestionBuilder.SuggestMode;
import org.elasticsearch.test.ESIntegTestCase;
import org.elasticsearch.test.hamcrest.ElasticsearchAssertions;
import java.io.IOException;
import java.net.URISyntaxException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ExecutionException;
import static org.elasticsearch.cluster.metadata.IndexMetaData.SETTING_NUMBER_OF_REPLICAS;
import static org.elasticsearch.cluster.metadata.IndexMetaData.SETTING_NUMBER_OF_SHARDS;
import static org.elasticsearch.common.settings.Settings.settingsBuilder;
import static org.elasticsearch.index.query.QueryBuilders.matchQuery;
import static org.elasticsearch.search.suggest.SuggestBuilders.phraseSuggestion;
import static org.elasticsearch.search.suggest.SuggestBuilders.termSuggestion;
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked;
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertNoFailures;
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertSuggestion;
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertSuggestionPhraseCollateMatchExists;
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertSuggestionSize;
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertThrows;
import static org.hamcrest.Matchers.anyOf;
import static org.hamcrest.Matchers.endsWith;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.Matchers.nullValue;
/**
* Integration tests for term and phrase suggestions. Many of these tests many requests that vary only slightly from one another. Where
* possible these tests should declare for the first request, make the request, modify the configuration for the next request, make that
@ -343,7 +343,7 @@ public class SuggestSearchTests extends ESIntegTestCase {
createIndex("test");
ensureGreen();
index("test", "type1", "1", "foo", "bar");
index("test", "type1", "1", "text", "bar");
refresh();
TermSuggestionBuilder termSuggest = termSuggestion("text")

View File

@ -19,6 +19,8 @@
package org.elasticsearch.index.reindex;
import java.io.IOException;
import org.elasticsearch.action.ActionRequest;
import org.elasticsearch.action.ActionRequestValidationException;
import org.elasticsearch.action.support.TransportAction;
@ -33,23 +35,25 @@ import org.elasticsearch.rest.RestChannel;
import org.elasticsearch.rest.RestRequest;
import org.elasticsearch.rest.RestStatus;
import org.elasticsearch.search.aggregations.AggregatorParsers;
import org.elasticsearch.search.suggest.Suggesters;
import org.elasticsearch.tasks.LoggingTaskListener;
import org.elasticsearch.tasks.Task;
import java.io.IOException;
public abstract class AbstractBaseReindexRestHandler<Request extends ActionRequest<Request>, Response extends BulkIndexByScrollResponse,
TA extends TransportAction<Request, Response>> extends BaseRestHandler {
protected final IndicesQueriesRegistry indicesQueriesRegistry;
protected final AggregatorParsers aggParsers;
protected final Suggesters suggesters;
private final ClusterService clusterService;
private final TA action;
protected AbstractBaseReindexRestHandler(Settings settings, Client client,
IndicesQueriesRegistry indicesQueriesRegistry, AggregatorParsers aggParsers, ClusterService clusterService, TA action) {
IndicesQueriesRegistry indicesQueriesRegistry, AggregatorParsers aggParsers, Suggesters suggesters,
ClusterService clusterService, TA action) {
super(settings, client);
this.indicesQueriesRegistry = indicesQueriesRegistry;
this.aggParsers = aggParsers;
this.suggesters = suggesters;
this.clusterService = clusterService;
this.action = action;
}

View File

@ -19,6 +19,14 @@
package org.elasticsearch.index.reindex;
import static org.elasticsearch.common.unit.TimeValue.parseTimeValue;
import static org.elasticsearch.rest.RestRequest.Method.POST;
import static org.elasticsearch.rest.RestStatus.BAD_REQUEST;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import org.elasticsearch.action.WriteConsistencyLevel;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.search.SearchRequest;
@ -43,14 +51,7 @@ import org.elasticsearch.rest.RestController;
import org.elasticsearch.rest.RestRequest;
import org.elasticsearch.script.Script;
import org.elasticsearch.search.aggregations.AggregatorParsers;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import static org.elasticsearch.common.unit.TimeValue.parseTimeValue;
import static org.elasticsearch.rest.RestRequest.Method.POST;
import static org.elasticsearch.rest.RestStatus.BAD_REQUEST;
import org.elasticsearch.search.suggest.Suggesters;
/**
* Expose IndexBySearchRequest over rest.
@ -76,7 +77,7 @@ public class RestReindexAction extends AbstractBaseReindexRestHandler<ReindexReq
builder.map(source);
parser = parser.contentType().xContent().createParser(builder.bytes());
context.queryParseContext.reset(parser);
search.source().parseXContent(parser, context.queryParseContext, context.aggParsers);
search.source().parseXContent(parser, context.queryParseContext, context.aggParsers, context.suggesters);
};
ObjectParser<IndexRequest, Void> destParser = new ObjectParser<>("dest");
@ -102,9 +103,9 @@ public class RestReindexAction extends AbstractBaseReindexRestHandler<ReindexReq
@Inject
public RestReindexAction(Settings settings, RestController controller, Client client,
IndicesQueriesRegistry indicesQueriesRegistry, AggregatorParsers aggParsers, ClusterService clusterService,
TransportReindexAction action) {
super(settings, client, indicesQueriesRegistry, aggParsers, clusterService, action);
IndicesQueriesRegistry indicesQueriesRegistry, AggregatorParsers aggParsers, Suggesters suggesters,
ClusterService clusterService, TransportReindexAction action) {
super(settings, client, indicesQueriesRegistry, aggParsers, suggesters, clusterService, action);
controller.registerHandler(POST, "/_reindex", this);
}
@ -118,7 +119,8 @@ public class RestReindexAction extends AbstractBaseReindexRestHandler<ReindexReq
ReindexRequest internalRequest = new ReindexRequest(new SearchRequest(), new IndexRequest());
try (XContentParser xcontent = XContentFactory.xContent(request.content()).createParser(request.content())) {
PARSER.parse(xcontent, internalRequest, new ReindexParseContext(new QueryParseContext(indicesQueriesRegistry), aggParsers));
PARSER.parse(xcontent, internalRequest, new ReindexParseContext(new QueryParseContext(indicesQueriesRegistry), aggParsers,
suggesters));
} catch (ParsingException e) {
logger.warn("Bad request", e);
badRequest(channel, e.getDetailedMessage());
@ -170,10 +172,13 @@ public class RestReindexAction extends AbstractBaseReindexRestHandler<ReindexReq
private class ReindexParseContext {
private final QueryParseContext queryParseContext;
private final AggregatorParsers aggParsers;
private final Suggesters suggesters;
public ReindexParseContext(QueryParseContext queryParseContext, AggregatorParsers aggParsers) {
public ReindexParseContext(QueryParseContext queryParseContext, AggregatorParsers aggParsers,
Suggesters suggesters) {
this.queryParseContext = queryParseContext;
this.aggParsers = aggParsers;
this.suggesters = suggesters;
}
}
}

View File

@ -19,6 +19,12 @@
package org.elasticsearch.index.reindex;
import static org.elasticsearch.index.reindex.AbstractBulkByScrollRequest.SIZE_ALL_MATCHES;
import static org.elasticsearch.index.reindex.RestReindexAction.parseCommon;
import static org.elasticsearch.rest.RestRequest.Method.POST;
import java.util.Map;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.client.Client;
import org.elasticsearch.cluster.ClusterService;
@ -38,20 +44,15 @@ import org.elasticsearch.rest.action.search.RestSearchAction;
import org.elasticsearch.rest.action.support.RestActions;
import org.elasticsearch.script.Script;
import org.elasticsearch.search.aggregations.AggregatorParsers;
import java.util.Map;
import static org.elasticsearch.index.reindex.AbstractBulkByScrollRequest.SIZE_ALL_MATCHES;
import static org.elasticsearch.index.reindex.RestReindexAction.parseCommon;
import static org.elasticsearch.rest.RestRequest.Method.POST;
import org.elasticsearch.search.suggest.Suggesters;
public class RestUpdateByQueryAction extends
AbstractBaseReindexRestHandler<UpdateByQueryRequest, BulkIndexByScrollResponse, TransportUpdateByQueryAction> {
@Inject
public RestUpdateByQueryAction(Settings settings, RestController controller, Client client,
IndicesQueriesRegistry indicesQueriesRegistry, AggregatorParsers aggParsers, ClusterService clusterService,
TransportUpdateByQueryAction action) {
super(settings, client, indicesQueriesRegistry, aggParsers, clusterService, action);
IndicesQueriesRegistry indicesQueriesRegistry, AggregatorParsers aggParsers, Suggesters suggesters,
ClusterService clusterService, TransportUpdateByQueryAction action) {
super(settings, client, indicesQueriesRegistry, aggParsers, suggesters, clusterService, action);
controller.registerHandler(POST, "/{index}/_update_by_query", this);
controller.registerHandler(POST, "/{index}/{type}/_update_by_query", this);
}
@ -96,7 +97,7 @@ public class RestUpdateByQueryAction extends
}
}
RestSearchAction.parseSearchRequest(internalRequest.getSearchRequest(), indicesQueriesRegistry, request,
parseFieldMatcher, aggParsers, bodyContent);
parseFieldMatcher, aggParsers, suggesters, bodyContent);
String conflicts = request.param("conflicts");
if (conflicts != null) {

View File

@ -33,6 +33,7 @@ import org.elasticsearch.search.dfs.DfsPhase;
import org.elasticsearch.search.fetch.FetchPhase;
import org.elasticsearch.search.internal.SearchContext;
import org.elasticsearch.search.query.QueryPhase;
import org.elasticsearch.search.suggest.Suggesters;
import org.elasticsearch.threadpool.ThreadPool;
import java.util.HashMap;
@ -69,9 +70,9 @@ public class MockSearchService extends SearchService {
public MockSearchService(Settings settings, ClusterSettings clusterSettings, ClusterService clusterService,
IndicesService indicesService, ThreadPool threadPool, ScriptService scriptService, PageCacheRecycler pageCacheRecycler,
BigArrays bigArrays, DfsPhase dfsPhase, QueryPhase queryPhase, FetchPhase fetchPhase,
AggregatorParsers aggParsers) {
AggregatorParsers aggParsers, Suggesters suggesters) {
super(settings, clusterSettings, clusterService, indicesService, threadPool, scriptService, pageCacheRecycler, bigArrays, dfsPhase,
queryPhase, fetchPhase, aggParsers);
queryPhase, fetchPhase, aggParsers, suggesters);
}
@Override