Merge pull request #16873 from abeyad/suggester-wiring-refactoring
Change internal representation of suggesters
This commit is contained in:
commit
31dcb3e18b
|
@ -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" />
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 + "]";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
*/
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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 + "]");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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"));
|
||||
|
|
|
@ -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]");
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -37,7 +37,7 @@ public class CustomSuggesterPlugin extends Plugin {
|
|||
}
|
||||
|
||||
public void onModule(SearchModule searchModule) {
|
||||
searchModule.registerSuggester("custom", CustomSuggester.class);
|
||||
searchModule.registerSuggester("custom", CustomSuggester.PROTOTYPE);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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]"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue