move parsing of search ext sections to the coordinating node

This commit is contained in:
javanna 2016-09-09 15:28:12 +02:00 committed by Luca Cavanna
parent 65c7f61ad9
commit 90ab460fcc
28 changed files with 309 additions and 216 deletions

View File

@ -989,7 +989,6 @@
<suppress files="modules[/\\]percolator[/\\]src[/\\]main[/\\]java[/\\]org[/\\]elasticsearch[/\\]percolator[/\\]MultiPercolateRequestBuilder.java" checks="LineLength" /> <suppress files="modules[/\\]percolator[/\\]src[/\\]main[/\\]java[/\\]org[/\\]elasticsearch[/\\]percolator[/\\]MultiPercolateRequestBuilder.java" checks="LineLength" />
<suppress files="modules[/\\]percolator[/\\]src[/\\]main[/\\]java[/\\]org[/\\]elasticsearch[/\\]percolator[/\\]PercolateShardResponse.java" checks="LineLength" /> <suppress files="modules[/\\]percolator[/\\]src[/\\]main[/\\]java[/\\]org[/\\]elasticsearch[/\\]percolator[/\\]PercolateShardResponse.java" checks="LineLength" />
<suppress files="modules[/\\]percolator[/\\]src[/\\]main[/\\]java[/\\]org[/\\]elasticsearch[/\\]percolator[/\\]TransportMultiPercolateAction.java" checks="LineLength" /> <suppress files="modules[/\\]percolator[/\\]src[/\\]main[/\\]java[/\\]org[/\\]elasticsearch[/\\]percolator[/\\]TransportMultiPercolateAction.java" checks="LineLength" />
<suppress files="modules[/\\]percolator[/\\]src[/\\]main[/\\]java[/\\]org[/\\]elasticsearch[/\\]percolator[/\\]TransportPercolateAction.java" checks="LineLength" />
<suppress files="modules[/\\]percolator[/\\]src[/\\]main[/\\]java[/\\]org[/\\]elasticsearch[/\\]percolator[/\\]TransportShardMultiPercolateAction.java" checks="LineLength" /> <suppress files="modules[/\\]percolator[/\\]src[/\\]main[/\\]java[/\\]org[/\\]elasticsearch[/\\]percolator[/\\]TransportShardMultiPercolateAction.java" checks="LineLength" />
<suppress files="modules[/\\]percolator[/\\]src[/\\]test[/\\]java[/\\]org[/\\]elasticsearch[/\\]percolator[/\\]MultiPercolatorIT.java" checks="LineLength" /> <suppress files="modules[/\\]percolator[/\\]src[/\\]test[/\\]java[/\\]org[/\\]elasticsearch[/\\]percolator[/\\]MultiPercolatorIT.java" checks="LineLength" />
<suppress files="modules[/\\]percolator[/\\]src[/\\]test[/\\]java[/\\]org[/\\]elasticsearch[/\\]percolator[/\\]PercolatorIT.java" checks="LineLength" /> <suppress files="modules[/\\]percolator[/\\]src[/\\]test[/\\]java[/\\]org[/\\]elasticsearch[/\\]percolator[/\\]PercolatorIT.java" checks="LineLength" />

View File

@ -25,10 +25,6 @@ import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects; import java.util.Objects;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.elasticsearch.plugins.Plugin;
/** /**
* A registry for {@link org.elasticsearch.common.io.stream.Writeable.Reader} readers of {@link NamedWriteable}. * A registry for {@link org.elasticsearch.common.io.stream.Writeable.Reader} readers of {@link NamedWriteable}.
@ -47,7 +43,7 @@ public class NamedWriteableRegistry {
/** A name for the writeable which is unique to the {@link #categoryClass}. */ /** A name for the writeable which is unique to the {@link #categoryClass}. */
public final String name; public final String name;
/** A reader captability of reading*/ /** A reader capability of reading*/
public final Writeable.Reader<?> reader; public final Writeable.Reader<?> reader;
/** Creates a new entry which can be stored by the registry. */ /** Creates a new entry which can be stored by the registry. */

View File

@ -871,6 +871,16 @@ public abstract class StreamOutput extends OutputStream {
} }
} }
/**
* Writes a list of strings
*/
public void writeStringList(List<String> list) throws IOException {
writeVInt(list.size());
for (String string: list) {
this.writeString(string);
}
}
/** /**
* Writes a list of {@link NamedWriteable} objects. * Writes a list of {@link NamedWriteable} objects.
*/ */

View File

@ -30,6 +30,7 @@ import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryParser; import org.elasticsearch.index.query.QueryParser;
import org.elasticsearch.index.query.functionscore.ScoreFunctionBuilder; import org.elasticsearch.index.query.functionscore.ScoreFunctionBuilder;
import org.elasticsearch.index.query.functionscore.ScoreFunctionParser; import org.elasticsearch.index.query.functionscore.ScoreFunctionParser;
import org.elasticsearch.search.SearchExtBuilder;
import org.elasticsearch.search.SearchExtParser; import org.elasticsearch.search.SearchExtParser;
import org.elasticsearch.search.aggregations.Aggregation; import org.elasticsearch.search.aggregations.Aggregation;
import org.elasticsearch.search.aggregations.AggregationBuilder; import org.elasticsearch.search.aggregations.AggregationBuilder;
@ -86,7 +87,7 @@ public interface SearchPlugin {
/** /**
* The new {@link SearchExtParser}s defined by this plugin. * The new {@link SearchExtParser}s defined by this plugin.
*/ */
default List<SearchExtParser> getSearchExtParsers() { default List<SearchExtSpec<?>> getSearchExts() {
return emptyList(); return emptyList();
} }
/** /**
@ -167,7 +168,7 @@ public interface SearchPlugin {
/** /**
* Specification for an {@link Aggregation}. * Specification for an {@link Aggregation}.
*/ */
public static class AggregationSpec extends SearchExtensionSpec<AggregationBuilder, Aggregator.Parser> { class AggregationSpec extends SearchExtensionSpec<AggregationBuilder, Aggregator.Parser> {
private final Map<String, Writeable.Reader<? extends InternalAggregation>> resultReaders = new TreeMap<>(); private final Map<String, Writeable.Reader<? extends InternalAggregation>> resultReaders = new TreeMap<>();
/** /**
@ -224,7 +225,7 @@ public interface SearchPlugin {
/** /**
* Specification for a {@link PipelineAggregator}. * Specification for a {@link PipelineAggregator}.
*/ */
public static class PipelineAggregationSpec extends SearchExtensionSpec<PipelineAggregationBuilder, PipelineAggregator.Parser> { class PipelineAggregationSpec extends SearchExtensionSpec<PipelineAggregationBuilder, PipelineAggregator.Parser> {
private final Map<String, Writeable.Reader<? extends InternalAggregation>> resultReaders = new TreeMap<>(); private final Map<String, Writeable.Reader<? extends InternalAggregation>> resultReaders = new TreeMap<>();
private final Writeable.Reader<? extends PipelineAggregator> aggregatorReader; private final Writeable.Reader<? extends PipelineAggregator> aggregatorReader;
@ -297,6 +298,19 @@ public interface SearchPlugin {
} }
} }
/**
* Specification for a {@link SearchExtBuilder} which represents an additional section that can be
* parsed in a search request (within the ext element).
*/
class SearchExtSpec<T extends SearchExtBuilder> extends SearchExtensionSpec<T, SearchExtParser<T>> {
public SearchExtSpec(ParseField name, Writeable.Reader<? extends T> reader, SearchExtParser<T> parser) {
super(name, reader, parser);
}
public SearchExtSpec(String name, Writeable.Reader<? extends T> reader, SearchExtParser<T> parser) {
super(name, reader, parser);
}
}
/** /**
* Specification of search time behavior extension like a custom {@link MovAvgModel} or {@link ScoreFunction}. * Specification of search time behavior extension like a custom {@link MovAvgModel} or {@link ScoreFunction}.

View File

@ -19,10 +19,6 @@
package org.elasticsearch.rest.action.search; package org.elasticsearch.rest.action.search;
import java.io.IOException;
import java.util.Map;
import java.util.function.BiConsumer;
import org.elasticsearch.ElasticsearchParseException; import org.elasticsearch.ElasticsearchParseException;
import org.elasticsearch.action.search.MultiSearchRequest; import org.elasticsearch.action.search.MultiSearchRequest;
import org.elasticsearch.action.search.SearchRequest; import org.elasticsearch.action.search.SearchRequest;
@ -40,12 +36,16 @@ import org.elasticsearch.index.query.QueryParseContext;
import org.elasticsearch.rest.BaseRestHandler; import org.elasticsearch.rest.BaseRestHandler;
import org.elasticsearch.rest.RestChannel; import org.elasticsearch.rest.RestChannel;
import org.elasticsearch.rest.RestController; import org.elasticsearch.rest.RestController;
import org.elasticsearch.rest.RestRequest; import org.elasticsearch.rest.RestRequest;
import org.elasticsearch.rest.action.RestActions; import org.elasticsearch.rest.action.RestActions;
import org.elasticsearch.rest.action.RestToXContentListener; import org.elasticsearch.rest.action.RestToXContentListener;
import org.elasticsearch.search.SearchRequestParsers; import org.elasticsearch.search.SearchRequestParsers;
import org.elasticsearch.search.builder.SearchSourceBuilder; import org.elasticsearch.search.builder.SearchSourceBuilder;
import java.io.IOException;
import java.util.Map;
import java.util.function.BiConsumer;
import static org.elasticsearch.common.xcontent.support.XContentMapValues.lenientNodeBooleanValue; import static org.elasticsearch.common.xcontent.support.XContentMapValues.lenientNodeBooleanValue;
import static org.elasticsearch.common.xcontent.support.XContentMapValues.nodeStringArrayValue; import static org.elasticsearch.common.xcontent.support.XContentMapValues.nodeStringArrayValue;
import static org.elasticsearch.common.xcontent.support.XContentMapValues.nodeStringValue; import static org.elasticsearch.common.xcontent.support.XContentMapValues.nodeStringValue;
@ -97,7 +97,7 @@ public class RestMultiSearchAction extends BaseRestHandler {
final QueryParseContext queryParseContext = new QueryParseContext(searchRequestParsers.queryParsers, final QueryParseContext queryParseContext = new QueryParseContext(searchRequestParsers.queryParsers,
requestParser, parseFieldMatcher); requestParser, parseFieldMatcher);
searchRequest.source(SearchSourceBuilder.fromXContent(queryParseContext, searchRequest.source(SearchSourceBuilder.fromXContent(queryParseContext,
searchRequestParsers.aggParsers, searchRequestParsers.suggesters)); searchRequestParsers.aggParsers, searchRequestParsers.suggesters, searchRequestParsers.searchExtParsers));
multiRequest.add(searchRequest); multiRequest.add(searchRequest);
} catch (IOException e) { } catch (IOException e) {
throw new ElasticsearchParseException("Exception when parsing search request", e); throw new ElasticsearchParseException("Exception when parsing search request", e);

View File

@ -102,7 +102,8 @@ public class RestSearchAction extends BaseRestHandler {
if (restContent != null) { if (restContent != null) {
try (XContentParser parser = XContentFactory.xContent(restContent).createParser(restContent)) { try (XContentParser parser = XContentFactory.xContent(restContent).createParser(restContent)) {
QueryParseContext context = new QueryParseContext(searchRequestParsers.queryParsers, parser, parseFieldMatcher); QueryParseContext context = new QueryParseContext(searchRequestParsers.queryParsers, parser, parseFieldMatcher);
searchRequest.source().parseXContent(context, searchRequestParsers.aggParsers, searchRequestParsers.suggesters); searchRequest.source().parseXContent(context, searchRequestParsers.aggParsers, searchRequestParsers.suggesters,
searchRequestParsers.searchExtParsers);
} }
} }

View File

@ -0,0 +1,48 @@
/*
* Licensed to Elasticsearch under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.elasticsearch.search;
import org.elasticsearch.common.io.stream.NamedWriteable;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.xcontent.ToXContent;
import org.elasticsearch.plugins.SearchPlugin;
/**
* Intermediate serializable representation of a search ext section. To be subclassed by plugins that support
* a custom section as part of a search request, which will be provided within the ext element.
* Any state needs to be serialized as part of the {@link org.elasticsearch.common.io.stream.Writeable#writeTo(StreamOutput)} method and
* read from the incoming stream, usually done adding a constructor that takes {@link org.elasticsearch.common.io.stream.StreamInput} as
* an argument.
*
* Registration happens through {@link SearchPlugin#getSearchExts()}, which also needs a {@link SearchExtParser} that's able to parse
* the incoming request from the REST layer into the proper {@link SearchExtBuilder} subclass.
*
* {@link #getWriteableName()} must return the same name as the one used for the registration
* of the {@link org.elasticsearch.plugins.SearchPlugin.SearchExtSpec}.
*
* @see SearchExtParser
* @see org.elasticsearch.plugins.SearchPlugin.SearchExtSpec
*/
public abstract class SearchExtBuilder implements NamedWriteable, ToXContent {
public abstract int hashCode();
public abstract boolean equals(Object obj);
}

View File

@ -21,18 +21,23 @@ package org.elasticsearch.search;
import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.common.xcontent.XContentParser;
import java.io.IOException;
/** /**
* Parser for the ext section of a search request, which can hold custom fetch sub phases config * Defines a parser that is able to parse {@link org.elasticsearch.search.SearchExtBuilder}s
* from {@link org.elasticsearch.common.xcontent.XContent}.
*
* Registration happens through {@link org.elasticsearch.plugins.SearchPlugin#getSearchExts()}, which also needs a {@link SearchExtBuilder}
* implementation which is the object that this parser returns when reading an incoming request form the REST layer.
*
* @see SearchExtBuilder
* @see org.elasticsearch.plugins.SearchPlugin.SearchExtSpec
*/ */
public interface SearchExtParser { @FunctionalInterface
public interface SearchExtParser<T extends SearchExtBuilder> {
/** /**
* Returns the name of the element that this parser is able to parse * Parses the supported element placed within the ext section of a search request
*/ */
String getName(); T fromXContent(XContentParser parser) throws IOException;
/**
* Parses the element whose name is returned by {@link #getName()}
*/
Object parse(XContentParser parser) throws Exception;
} }

View File

@ -24,9 +24,9 @@ import org.elasticsearch.common.xcontent.ParseFieldRegistry;
/** /**
* Extensions to ParseFieldRegistry to make Guice happy. * Extensions to ParseFieldRegistry to make Guice happy.
*/ */
public class SearchExtParserRegistry extends ParseFieldRegistry<SearchExtParser> { public class SearchExtRegistry extends ParseFieldRegistry<SearchExtParser> {
SearchExtParserRegistry() { public SearchExtRegistry() {
super("ext"); super("ext");
} }
} }

View File

@ -93,6 +93,7 @@ import org.elasticsearch.plugins.SearchPlugin.FetchPhaseConstructionContext;
import org.elasticsearch.plugins.SearchPlugin.PipelineAggregationSpec; import org.elasticsearch.plugins.SearchPlugin.PipelineAggregationSpec;
import org.elasticsearch.plugins.SearchPlugin.QuerySpec; import org.elasticsearch.plugins.SearchPlugin.QuerySpec;
import org.elasticsearch.plugins.SearchPlugin.ScoreFunctionSpec; import org.elasticsearch.plugins.SearchPlugin.ScoreFunctionSpec;
import org.elasticsearch.plugins.SearchPlugin.SearchExtSpec;
import org.elasticsearch.plugins.SearchPlugin.SearchExtensionSpec; import org.elasticsearch.plugins.SearchPlugin.SearchExtensionSpec;
import org.elasticsearch.search.action.SearchTransportService; import org.elasticsearch.search.action.SearchTransportService;
import org.elasticsearch.search.aggregations.AggregationBuilder; import org.elasticsearch.search.aggregations.AggregationBuilder;
@ -306,7 +307,7 @@ public class SearchModule extends AbstractModule {
"moving_avg_model"); "moving_avg_model");
private final List<FetchSubPhase> fetchSubPhases = new ArrayList<>(); private final List<FetchSubPhase> fetchSubPhases = new ArrayList<>();
private final SearchExtParserRegistry searchExtParserRegistry = new SearchExtParserRegistry(); private final SearchExtRegistry searchExtParserRegistry = new SearchExtRegistry();
private final Settings settings; private final Settings settings;
private final List<Entry> namedWriteables = new ArrayList<>(); private final List<Entry> namedWriteables = new ArrayList<>();
@ -327,9 +328,9 @@ public class SearchModule extends AbstractModule {
registerAggregations(plugins); registerAggregations(plugins);
registerPipelineAggregations(plugins); registerPipelineAggregations(plugins);
registerFetchSubPhases(plugins); registerFetchSubPhases(plugins);
registerSearchExtParsers(plugins); registerSearchExts(plugins);
registerShapes(); registerShapes();
searchRequestParsers = new SearchRequestParsers(queryParserRegistry, aggregatorParsers, getSuggesters()); searchRequestParsers = new SearchRequestParsers(queryParserRegistry, aggregatorParsers, getSuggesters(), searchExtParserRegistry);
} }
public List<Entry> getNamedWriteables() { public List<Entry> getNamedWriteables() {
@ -382,7 +383,7 @@ public class SearchModule extends AbstractModule {
if (false == transportClient) { if (false == transportClient) {
bind(IndicesQueriesRegistry.class).toInstance(queryParserRegistry); bind(IndicesQueriesRegistry.class).toInstance(queryParserRegistry);
bind(SearchRequestParsers.class).toInstance(searchRequestParsers); bind(SearchRequestParsers.class).toInstance(searchRequestParsers);
bind(SearchExtParserRegistry.class).toInstance(searchExtParserRegistry); bind(SearchExtRegistry.class).toInstance(searchExtParserRegistry);
configureSearch(); configureSearch();
} }
} }
@ -728,12 +729,13 @@ public class SearchModule extends AbstractModule {
registerFromPlugin(plugins, p -> p.getFetchSubPhases(context), this::registerFetchSubPhase); registerFromPlugin(plugins, p -> p.getFetchSubPhases(context), this::registerFetchSubPhase);
} }
private void registerSearchExtParsers(List<SearchPlugin> plugins) { private void registerSearchExts(List<SearchPlugin> plugins) {
registerFromPlugin(plugins, SearchPlugin::getSearchExtParsers, this::registerSearchExtParser); registerFromPlugin(plugins, SearchPlugin::getSearchExts, this::registerSearchExt);
} }
private void registerSearchExtParser(SearchExtParser searchExtParser) { private void registerSearchExt(SearchExtSpec<?> spec) {
searchExtParserRegistry.register(searchExtParser, searchExtParser.getName()); searchExtParserRegistry.register(spec.getParser(), spec.getName());
namedWriteables.add(new Entry(SearchExtBuilder.class, spec.getName().getPreferredName(), spec.getReader()));
} }
private void registerFetchSubPhase(FetchSubPhase subPhase) { private void registerFetchSubPhase(FetchSubPhase subPhase) {

View File

@ -37,7 +37,8 @@ public class SearchRequestParsers {
/** /**
* Query parsers that may be used in search requests. * Query parsers that may be used in search requests.
* @see org.elasticsearch.index.query.QueryParseContext * @see org.elasticsearch.index.query.QueryParseContext
* @see org.elasticsearch.search.builder.SearchSourceBuilder#fromXContent(QueryParseContext, AggregatorParsers, Suggesters) * @see org.elasticsearch.search.builder.SearchSourceBuilder#fromXContent(QueryParseContext, AggregatorParsers,
* Suggesters, SearchExtRegistry)
*/ */
public final IndicesQueriesRegistry queryParsers; public final IndicesQueriesRegistry queryParsers;
@ -45,20 +46,29 @@ public class SearchRequestParsers {
// and pipeline agg parsers should be here // and pipeline agg parsers should be here
/** /**
* Agg and pipeline agg parsers that may be used in search requests. * Agg and pipeline agg parsers that may be used in search requests.
* @see org.elasticsearch.search.builder.SearchSourceBuilder#fromXContent(QueryParseContext, AggregatorParsers, Suggesters) * @see org.elasticsearch.search.builder.SearchSourceBuilder#fromXContent(QueryParseContext, AggregatorParsers,
* Suggesters, SearchExtRegistry)
*/ */
public final AggregatorParsers aggParsers; public final AggregatorParsers aggParsers;
// TODO: Suggesters should be removed and the underlying map moved here // TODO: Suggesters should be removed and the underlying map moved here
/** /**
* Suggesters that may be used in search requests. * Suggesters that may be used in search requests.
* @see org.elasticsearch.search.builder.SearchSourceBuilder#fromXContent(QueryParseContext, AggregatorParsers, Suggesters) * @see org.elasticsearch.search.builder.SearchSourceBuilder#fromXContent(QueryParseContext, AggregatorParsers,
* Suggesters, SearchExtRegistry)
*/ */
public final Suggesters suggesters; public final Suggesters suggesters;
public SearchRequestParsers(IndicesQueriesRegistry queryParsers, AggregatorParsers aggParsers, Suggesters suggesters) { /**
* Pluggable section that can be parsed out of a search section, within the ext element
*/
public final SearchExtRegistry searchExtParsers;
public SearchRequestParsers(IndicesQueriesRegistry queryParsers, AggregatorParsers aggParsers, Suggesters suggesters,
SearchExtRegistry searchExtParsers) {
this.queryParsers = queryParsers; this.queryParsers = queryParsers;
this.aggParsers = aggParsers; this.aggParsers = aggParsers;
this.suggesters = suggesters; this.suggesters = suggesters;
this.searchExtParsers = searchExtParsers;
} }
} }

View File

@ -39,9 +39,6 @@ import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.util.BigArrays; import org.elasticsearch.common.util.BigArrays;
import org.elasticsearch.common.util.concurrent.ConcurrentCollections; import org.elasticsearch.common.util.concurrent.ConcurrentCollections;
import org.elasticsearch.common.util.concurrent.ConcurrentMapLong; import org.elasticsearch.common.util.concurrent.ConcurrentMapLong;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.common.xcontent.XContentLocation;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.index.Index; import org.elasticsearch.index.Index;
import org.elasticsearch.index.IndexService; import org.elasticsearch.index.IndexService;
import org.elasticsearch.index.engine.Engine; import org.elasticsearch.index.engine.Engine;
@ -142,14 +139,11 @@ public class SearchService extends AbstractLifecycleComponent implements IndexEv
private final ConcurrentMapLong<SearchContext> activeContexts = ConcurrentCollections.newConcurrentMapLongWithAggressiveConcurrency(); private final ConcurrentMapLong<SearchContext> activeContexts = ConcurrentCollections.newConcurrentMapLongWithAggressiveConcurrency();
private final SearchExtParserRegistry searchExtParserRegistry;
private final ParseFieldMatcher parseFieldMatcher; private final ParseFieldMatcher parseFieldMatcher;
@Inject @Inject
public SearchService(Settings settings, ClusterSettings clusterSettings, ClusterService clusterService, IndicesService indicesService, public SearchService(Settings settings, ClusterSettings clusterSettings, ClusterService clusterService, IndicesService indicesService,
ThreadPool threadPool, ScriptService scriptService, BigArrays bigArrays, FetchPhase fetchPhase, ThreadPool threadPool, ScriptService scriptService, BigArrays bigArrays, FetchPhase fetchPhase) {
SearchExtParserRegistry searchExtParserRegistry) {
super(settings); super(settings);
this.parseFieldMatcher = new ParseFieldMatcher(settings); this.parseFieldMatcher = new ParseFieldMatcher(settings);
this.threadPool = threadPool; this.threadPool = threadPool;
@ -165,8 +159,6 @@ public class SearchService extends AbstractLifecycleComponent implements IndexEv
this.keepAliveReaper = threadPool.scheduleWithFixedDelay(new Reaper(), keepAliveInterval, Names.SAME); this.keepAliveReaper = threadPool.scheduleWithFixedDelay(new Reaper(), keepAliveInterval, Names.SAME);
this.searchExtParserRegistry = searchExtParserRegistry;
defaultSearchTimeout = DEFAULT_SEARCH_TIMEOUT_SETTING.get(settings); defaultSearchTimeout = DEFAULT_SEARCH_TIMEOUT_SETTING.get(settings);
clusterSettings.addSettingsUpdateConsumer(DEFAULT_SEARCH_TIMEOUT_SETTING, this::setDefaultSearchTimeout); clusterSettings.addSettingsUpdateConsumer(DEFAULT_SEARCH_TIMEOUT_SETTING, this::setDefaultSearchTimeout);
} }
@ -749,39 +741,8 @@ public class SearchService extends AbstractLifecycleComponent implements IndexEv
} }
} }
if (source.ext() != null) { if (source.ext() != null) {
XContentParser extParser = null; for (SearchExtBuilder searchExtBuilder : source.ext()) {
try { context.addSearchExt(searchExtBuilder);
extParser = XContentFactory.xContent(source.ext()).createParser(source.ext());
if (extParser.nextToken() != XContentParser.Token.START_OBJECT) {
throw new SearchParseException(context, "expected start object, found [" + extParser.currentToken() + "] instead",
extParser.getTokenLocation());
}
XContentParser.Token token;
String currentFieldName = null;
while ((token = extParser.nextToken()) != XContentParser.Token.END_OBJECT) {
if (token == XContentParser.Token.FIELD_NAME) {
currentFieldName = extParser.currentName();
} else {
SearchExtParser searchExtParser = this.searchExtParserRegistry.lookup(currentFieldName, parseFieldMatcher,
extParser.getTokenLocation());
Object searchExtBuilder = searchExtParser.parse(extParser);
context.putSearchExtBuilder(currentFieldName, searchExtBuilder);
}
}
} catch (Exception e) {
String sSource = "_na_";
try {
sSource = source.toString();
} catch (Exception inner) {
e.addSuppressed(inner);
// ignore
}
XContentLocation location = extParser != null ? extParser.getTokenLocation() : null;
throw new SearchParseException(context, "failed to parse ext source [" + sSource + "]", location, e);
} finally {
if (extParser != null) {
extParser.close();
}
} }
} }
if (source.version() != null) { if (source.version() != null) {

View File

@ -25,7 +25,6 @@ import org.elasticsearch.common.Nullable;
import org.elasticsearch.common.ParseField; import org.elasticsearch.common.ParseField;
import org.elasticsearch.common.ParsingException; import org.elasticsearch.common.ParsingException;
import org.elasticsearch.common.Strings; import org.elasticsearch.common.Strings;
import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.collect.Tuple; import org.elasticsearch.common.collect.Tuple;
import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput; import org.elasticsearch.common.io.stream.StreamOutput;
@ -33,13 +32,14 @@ import org.elasticsearch.common.io.stream.Writeable;
import org.elasticsearch.common.unit.TimeValue; import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.ToXContent; import org.elasticsearch.common.xcontent.ToXContent;
import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.QueryBuilder; import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryParseContext; import org.elasticsearch.index.query.QueryParseContext;
import org.elasticsearch.index.query.QueryShardContext; import org.elasticsearch.index.query.QueryShardContext;
import org.elasticsearch.script.Script; import org.elasticsearch.script.Script;
import org.elasticsearch.search.SearchExtBuilder;
import org.elasticsearch.search.SearchExtParser;
import org.elasticsearch.search.SearchExtRegistry;
import org.elasticsearch.search.aggregations.AggregationBuilder; import org.elasticsearch.search.aggregations.AggregationBuilder;
import org.elasticsearch.search.aggregations.AggregatorFactories; import org.elasticsearch.search.aggregations.AggregatorFactories;
import org.elasticsearch.search.aggregations.AggregatorParsers; import org.elasticsearch.search.aggregations.AggregatorParsers;
@ -108,9 +108,9 @@ public final class SearchSourceBuilder extends ToXContentToBytes implements Writ
public static final ParseField SLICE = new ParseField("slice"); public static final ParseField SLICE = new ParseField("slice");
public static SearchSourceBuilder fromXContent(QueryParseContext context, AggregatorParsers aggParsers, public static SearchSourceBuilder fromXContent(QueryParseContext context, AggregatorParsers aggParsers,
Suggesters suggesters) throws IOException { Suggesters suggesters, SearchExtRegistry searchExtRegistry) throws IOException {
SearchSourceBuilder builder = new SearchSourceBuilder(); SearchSourceBuilder builder = new SearchSourceBuilder();
builder.parseXContent(context, aggParsers, suggesters); builder.parseXContent(context, aggParsers, suggesters, searchExtRegistry);
return builder; return builder;
} }
@ -164,13 +164,13 @@ public final class SearchSourceBuilder extends ToXContentToBytes implements Writ
private SuggestBuilder suggestBuilder; private SuggestBuilder suggestBuilder;
private List<RescoreBuilder<?>> rescoreBuilders; private List<RescoreBuilder> rescoreBuilders;
private ObjectFloatHashMap<String> indexBoost = null; private ObjectFloatHashMap<String> indexBoost = null;
private List<String> stats; private List<String> stats;
private BytesReference ext = null; private List<SearchExtBuilder> extBuilders;
private boolean profile = false; private boolean profile = false;
@ -203,18 +203,10 @@ public final class SearchSourceBuilder extends ToXContentToBytes implements Writ
postQueryBuilder = in.readOptionalNamedWriteable(QueryBuilder.class); postQueryBuilder = in.readOptionalNamedWriteable(QueryBuilder.class);
queryBuilder = in.readOptionalNamedWriteable(QueryBuilder.class); queryBuilder = in.readOptionalNamedWriteable(QueryBuilder.class);
if (in.readBoolean()) { if (in.readBoolean()) {
int size = in.readVInt(); rescoreBuilders = in.readNamedWriteableList(RescoreBuilder.class);
rescoreBuilders = new ArrayList<>();
for (int i = 0; i < size; i++) {
rescoreBuilders.add(in.readNamedWriteable(RescoreBuilder.class));
}
} }
if (in.readBoolean()) { if (in.readBoolean()) {
int size = in.readVInt(); scriptFields = in.readList(ScriptField::new);
scriptFields = new ArrayList<>(size);
for (int i = 0; i < size; i++) {
scriptFields.add(new ScriptField(in));
}
} }
size = in.readVInt(); size = in.readVInt();
if (in.readBoolean()) { if (in.readBoolean()) {
@ -225,18 +217,16 @@ public final class SearchSourceBuilder extends ToXContentToBytes implements Writ
} }
} }
if (in.readBoolean()) { if (in.readBoolean()) {
int size = in.readVInt(); stats = in.readList(StreamInput::readString);
stats = new ArrayList<>();
for (int i = 0; i < size; i++) {
stats.add(in.readString());
}
} }
suggestBuilder = in.readOptionalWriteable(SuggestBuilder::new); suggestBuilder = in.readOptionalWriteable(SuggestBuilder::new);
terminateAfter = in.readVInt(); terminateAfter = in.readVInt();
timeout = in.readOptionalWriteable(TimeValue::new); timeout = in.readOptionalWriteable(TimeValue::new);
trackScores = in.readBoolean(); trackScores = in.readBoolean();
version = in.readOptionalBoolean(); version = in.readOptionalBoolean();
ext = in.readOptionalBytesReference(); if (in.readBoolean()) {
extBuilders = in.readNamedWriteableList(SearchExtBuilder.class);
}
profile = in.readBoolean(); profile = in.readBoolean();
searchAfterBuilder = in.readOptionalWriteable(SearchAfterBuilder::new); searchAfterBuilder = in.readOptionalWriteable(SearchAfterBuilder::new);
sliceBuilder = in.readOptionalWriteable(SliceBuilder::new); sliceBuilder = in.readOptionalWriteable(SliceBuilder::new);
@ -262,18 +252,12 @@ public final class SearchSourceBuilder extends ToXContentToBytes implements Writ
boolean hasRescoreBuilders = rescoreBuilders != null; boolean hasRescoreBuilders = rescoreBuilders != null;
out.writeBoolean(hasRescoreBuilders); out.writeBoolean(hasRescoreBuilders);
if (hasRescoreBuilders) { if (hasRescoreBuilders) {
out.writeVInt(rescoreBuilders.size()); out.writeNamedWriteableList(rescoreBuilders);
for (RescoreBuilder<?> rescoreBuilder : rescoreBuilders) {
out.writeNamedWriteable(rescoreBuilder);
}
} }
boolean hasScriptFields = scriptFields != null; boolean hasScriptFields = scriptFields != null;
out.writeBoolean(hasScriptFields); out.writeBoolean(hasScriptFields);
if (hasScriptFields) { if (hasScriptFields) {
out.writeVInt(scriptFields.size()); out.writeList(scriptFields);
for (ScriptField scriptField : scriptFields) {
scriptField.writeTo(out);
}
} }
out.writeVInt(size); out.writeVInt(size);
boolean hasSorts = sorts != null; boolean hasSorts = sorts != null;
@ -287,17 +271,19 @@ public final class SearchSourceBuilder extends ToXContentToBytes implements Writ
boolean hasStats = stats != null; boolean hasStats = stats != null;
out.writeBoolean(hasStats); out.writeBoolean(hasStats);
if (hasStats) { if (hasStats) {
out.writeVInt(stats.size()); out.writeStringList(stats);
for (String stat : stats) {
out.writeString(stat);
}
} }
out.writeOptionalWriteable(suggestBuilder); out.writeOptionalWriteable(suggestBuilder);
out.writeVInt(terminateAfter); out.writeVInt(terminateAfter);
out.writeOptionalWriteable(timeout); out.writeOptionalWriteable(timeout);
out.writeBoolean(trackScores); out.writeBoolean(trackScores);
out.writeOptionalBoolean(version); out.writeOptionalBoolean(version);
out.writeOptionalBytesReference(ext); if (extBuilders == null) {
out.writeBoolean(false);
} else {
out.writeBoolean(true);
out.writeNamedWriteableList(extBuilders);
}
out.writeBoolean(profile); out.writeBoolean(profile);
out.writeOptionalWriteable(searchAfterBuilder); out.writeOptionalWriteable(searchAfterBuilder);
out.writeOptionalWriteable(sliceBuilder); out.writeOptionalWriteable(sliceBuilder);
@ -649,7 +635,7 @@ public final class SearchSourceBuilder extends ToXContentToBytes implements Writ
/** /**
* Gets the bytes representing the rescore builders for this request. * Gets the bytes representing the rescore builders for this request.
*/ */
public List<RescoreBuilder<?>> rescores() { public List<RescoreBuilder> rescores() {
return rescoreBuilders; return rescoreBuilders;
} }
@ -875,13 +861,13 @@ public final class SearchSourceBuilder extends ToXContentToBytes implements Writ
return stats; return stats;
} }
public SearchSourceBuilder ext(XContentBuilder ext) { public SearchSourceBuilder ext(List<SearchExtBuilder> searchExtBuilders) {
this.ext = ext.bytes(); this.extBuilders = searchExtBuilders;
return this; return this;
} }
public BytesReference ext() { public List<SearchExtBuilder> ext() {
return ext; return extBuilders;
} }
/** /**
@ -919,7 +905,7 @@ public final class SearchSourceBuilder extends ToXContentToBytes implements Writ
SearchSourceBuilder rewrittenBuilder = new SearchSourceBuilder(); SearchSourceBuilder rewrittenBuilder = new SearchSourceBuilder();
rewrittenBuilder.aggregations = aggregations; rewrittenBuilder.aggregations = aggregations;
rewrittenBuilder.explain = explain; rewrittenBuilder.explain = explain;
rewrittenBuilder.ext = ext; rewrittenBuilder.extBuilders = extBuilders;
rewrittenBuilder.fetchSourceContext = fetchSourceContext; rewrittenBuilder.fetchSourceContext = fetchSourceContext;
rewrittenBuilder.docValueFields = docValueFields; rewrittenBuilder.docValueFields = docValueFields;
rewrittenBuilder.storedFieldsContext = storedFieldsContext; rewrittenBuilder.storedFieldsContext = storedFieldsContext;
@ -948,9 +934,10 @@ public final class SearchSourceBuilder extends ToXContentToBytes implements Writ
/** /**
* Parse some xContent into this SearchSourceBuilder, overwriting any values specified in the xContent. Use this if you need to set up * 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 * different defaults than a regular SearchSourceBuilder would have and use
* {@link #fromXContent(QueryParseContext, AggregatorParsers, Suggesters)} if you have normal defaults. * {@link #fromXContent(QueryParseContext, AggregatorParsers, Suggesters, SearchExtRegistry)} if you have normal defaults.
*/ */
public void parseXContent(QueryParseContext context, AggregatorParsers aggParsers, Suggesters suggesters) public void parseXContent(QueryParseContext context, AggregatorParsers aggParsers,
Suggesters suggesters, SearchExtRegistry searchExtRegistry)
throws IOException { throws IOException {
XContentParser parser = context.parser(); XContentParser parser = context.parser();
@ -1034,8 +1021,23 @@ public final class SearchSourceBuilder extends ToXContentToBytes implements Writ
rescoreBuilders = new ArrayList<>(); rescoreBuilders = new ArrayList<>();
rescoreBuilders.add(RescoreBuilder.parseFromXContent(context)); rescoreBuilders.add(RescoreBuilder.parseFromXContent(context));
} else if (context.getParseFieldMatcher().match(currentFieldName, EXT_FIELD)) { } else if (context.getParseFieldMatcher().match(currentFieldName, EXT_FIELD)) {
XContentBuilder xContentBuilder = XContentFactory.jsonBuilder().copyCurrentStructure(parser); extBuilders = new ArrayList<>();
ext = xContentBuilder.bytes(); String extSectionName = null;
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
if (token == XContentParser.Token.FIELD_NAME) {
extSectionName = parser.currentName();
} else {
SearchExtParser searchExtParser = searchExtRegistry.lookup(extSectionName,
context.getParseFieldMatcher(), parser.getTokenLocation());
SearchExtBuilder searchExtBuilder = searchExtParser.fromXContent(parser);
if (searchExtBuilder.getWriteableName().equals(extSectionName) == false) {
throw new IllegalStateException("The parsed [" + searchExtBuilder.getClass().getName() + "] object has a "
+ "different writeable name compared to the name of the section that it was parsed from: found ["
+ searchExtBuilder.getWriteableName() + "] expected [" + extSectionName + "]");
}
extBuilders.add(searchExtBuilder);
}
}
} else if (context.getParseFieldMatcher().match(currentFieldName, SLICE)) { } else if (context.getParseFieldMatcher().match(currentFieldName, SLICE)) {
sliceBuilder = SliceBuilder.fromXContent(context); sliceBuilder = SliceBuilder.fromXContent(context);
} else { } else {
@ -1221,12 +1223,12 @@ public final class SearchSourceBuilder extends ToXContentToBytes implements Writ
builder.field(STATS_FIELD.getPreferredName(), stats); builder.field(STATS_FIELD.getPreferredName(), stats);
} }
if (ext != null) { if (extBuilders != null) {
builder.field(EXT_FIELD.getPreferredName()); builder.startObject(EXT_FIELD.getPreferredName());
try (XContentParser parser = XContentFactory.xContent(XContentType.JSON).createParser(ext)) { for (SearchExtBuilder extBuilder : extBuilders) {
parser.nextToken(); extBuilder.toXContent(builder, params);
builder.copyCurrentStructure(parser);
} }
builder.endObject();
} }
} }
@ -1344,9 +1346,9 @@ public final class SearchSourceBuilder extends ToXContentToBytes implements Writ
@Override @Override
public int hashCode() { public int hashCode() {
return Objects.hash(aggregations, explain, fetchSourceContext, docValueFields, storedFieldsContext, from, return Objects.hash(aggregations, explain, fetchSourceContext, docValueFields, storedFieldsContext, from, highlightBuilder,
highlightBuilder, indexBoost, minScore, postQueryBuilder, queryBuilder, rescoreBuilders, scriptFields, size, sorts, indexBoost, minScore, postQueryBuilder, queryBuilder, rescoreBuilders, scriptFields, size, sorts, searchAfterBuilder,
searchAfterBuilder, sliceBuilder, stats, suggestBuilder, terminateAfter, timeout, trackScores, version, profile); sliceBuilder, stats, suggestBuilder, terminateAfter, timeout, trackScores, version, profile, extBuilders);
} }
@Override @Override
@ -1381,7 +1383,7 @@ public final class SearchSourceBuilder extends ToXContentToBytes implements Writ
&& Objects.equals(timeout, other.timeout) && Objects.equals(timeout, other.timeout)
&& Objects.equals(trackScores, other.trackScores) && Objects.equals(trackScores, other.trackScores)
&& Objects.equals(version, other.version) && Objects.equals(version, other.version)
&& Objects.equals(profile, other.profile); && Objects.equals(profile, other.profile)
&& Objects.equals(extBuilders, other.extBuilders);
} }
} }

View File

@ -53,6 +53,7 @@ import org.elasticsearch.index.query.QueryShardContext;
import org.elasticsearch.index.shard.IndexShard; import org.elasticsearch.index.shard.IndexShard;
import org.elasticsearch.index.similarity.SimilarityService; import org.elasticsearch.index.similarity.SimilarityService;
import org.elasticsearch.script.ScriptService; import org.elasticsearch.script.ScriptService;
import org.elasticsearch.search.SearchExtBuilder;
import org.elasticsearch.search.SearchShardTarget; import org.elasticsearch.search.SearchShardTarget;
import org.elasticsearch.search.aggregations.SearchContextAggregations; import org.elasticsearch.search.aggregations.SearchContextAggregations;
import org.elasticsearch.search.dfs.DfsSearchResult; import org.elasticsearch.search.dfs.DfsSearchResult;
@ -145,7 +146,7 @@ public class DefaultSearchContext extends SearchContext {
private volatile long lastAccessTime = -1; private volatile long lastAccessTime = -1;
private Profilers profilers; private Profilers profilers;
private final Map<String, Object> searchExtBuilders = new HashMap<>(); private final Map<String, SearchExtBuilder> searchExtBuilders = new HashMap<>();
private final Map<Class<?>, Collector> queryCollectors = new HashMap<>(); private final Map<Class<?>, Collector> queryCollectors = new HashMap<>();
private final QueryShardContext queryShardContext; private final QueryShardContext queryShardContext;
private FetchPhase fetchPhase; private FetchPhase fetchPhase;
@ -385,13 +386,15 @@ public class DefaultSearchContext extends SearchContext {
} }
@Override @Override
public Object getSearchExtBuilder(String name) { public void addSearchExt(SearchExtBuilder searchExtBuilder) {
return searchExtBuilders.get(name); //it's ok to use the writeable name here given that we enforce it to be the same as the name of the element that gets
//parsed by the corresponding parser. There is one single name and one single way to retrieve the parsed object from the context.
searchExtBuilders.put(searchExtBuilder.getWriteableName(), searchExtBuilder);
} }
@Override @Override
public void putSearchExtBuilder(String name, Object searchExtBuilder) { public SearchExtBuilder getSearchExt(String name) {
searchExtBuilders.put(name, searchExtBuilder); return searchExtBuilders.get(name);
} }
@Override @Override

View File

@ -38,6 +38,7 @@ import org.elasticsearch.index.query.QueryShardContext;
import org.elasticsearch.index.shard.IndexShard; import org.elasticsearch.index.shard.IndexShard;
import org.elasticsearch.index.similarity.SimilarityService; import org.elasticsearch.index.similarity.SimilarityService;
import org.elasticsearch.script.ScriptService; import org.elasticsearch.script.ScriptService;
import org.elasticsearch.search.SearchExtBuilder;
import org.elasticsearch.search.SearchShardTarget; import org.elasticsearch.search.SearchShardTarget;
import org.elasticsearch.search.aggregations.SearchContextAggregations; import org.elasticsearch.search.aggregations.SearchContextAggregations;
import org.elasticsearch.search.dfs.DfsSearchResult; import org.elasticsearch.search.dfs.DfsSearchResult;
@ -510,13 +511,13 @@ public abstract class FilteredSearchContext extends SearchContext {
} }
@Override @Override
public void putSearchExtBuilder(String name, Object fetchSubPhaseBuilder) { public void addSearchExt(SearchExtBuilder searchExtBuilder) {
in.putSearchExtBuilder(name, fetchSubPhaseBuilder); in.addSearchExt(searchExtBuilder);
} }
@Override @Override
public Object getSearchExtBuilder(String name) { public SearchExtBuilder getSearchExt(String name) {
return in.getSearchExtBuilder(name); return in.getSearchExt(name);
} }
@Override @Override

View File

@ -44,6 +44,7 @@ import org.elasticsearch.index.query.QueryShardContext;
import org.elasticsearch.index.shard.IndexShard; import org.elasticsearch.index.shard.IndexShard;
import org.elasticsearch.index.similarity.SimilarityService; import org.elasticsearch.index.similarity.SimilarityService;
import org.elasticsearch.script.ScriptService; import org.elasticsearch.script.ScriptService;
import org.elasticsearch.search.SearchExtBuilder;
import org.elasticsearch.search.SearchShardTarget; import org.elasticsearch.search.SearchShardTarget;
import org.elasticsearch.search.aggregations.SearchContextAggregations; import org.elasticsearch.search.aggregations.SearchContextAggregations;
import org.elasticsearch.search.dfs.DfsSearchResult; import org.elasticsearch.search.dfs.DfsSearchResult;
@ -184,9 +185,9 @@ public abstract class SearchContext extends AbstractRefCounted implements Releas
public abstract SearchContext aggregations(SearchContextAggregations aggregations); public abstract SearchContext aggregations(SearchContextAggregations aggregations);
public abstract void putSearchExtBuilder(String name, Object fetchSubPhaseBuilder); public abstract void addSearchExt(SearchExtBuilder searchExtBuilder);
public abstract Object getSearchExtBuilder(String name); public abstract SearchExtBuilder getSearchExt(String name);
public abstract SearchContextHighlight highlight(); public abstract SearchContextHighlight highlight();

View File

@ -175,6 +175,6 @@ public class MultiSearchRequestTests extends ESTestCase {
IndicesQueriesRegistry registry = new IndicesQueriesRegistry(); IndicesQueriesRegistry registry = new IndicesQueriesRegistry();
QueryParser<MatchAllQueryBuilder> parser = MatchAllQueryBuilder::fromXContent; QueryParser<MatchAllQueryBuilder> parser = MatchAllQueryBuilder::fromXContent;
registry.register(parser, MatchAllQueryBuilder.NAME); registry.register(parser, MatchAllQueryBuilder.NAME);
return new SearchRequestParsers(registry, null, null); return new SearchRequestParsers(registry, null, null, null);
} }
} }

View File

@ -29,6 +29,7 @@ import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.unit.TimeValue; import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.indices.IndicesModule; import org.elasticsearch.indices.IndicesModule;
import org.elasticsearch.search.fetch.FetchSubPhasePluginIT;
import org.elasticsearch.test.ESTestCase; import org.elasticsearch.test.ESTestCase;
import org.junit.AfterClass; import org.junit.AfterClass;
import org.junit.BeforeClass; import org.junit.BeforeClass;
@ -36,6 +37,7 @@ import org.junit.BeforeClass;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections;
import java.util.List; import java.util.List;
import static java.util.Collections.emptyList; import static java.util.Collections.emptyList;
@ -53,7 +55,8 @@ public class SearchRequestTests extends ESTestCase {
bindMapperExtension(); bindMapperExtension();
} }
}; };
SearchModule searchModule = new SearchModule(Settings.EMPTY, false, emptyList()) { SearchModule searchModule = new SearchModule(Settings.EMPTY, false,
Collections.singletonList(new FetchSubPhasePluginIT.FetchTermVectorsPlugin())) {
@Override @Override
protected void configureSearch() { protected void configureSearch() {
// Skip me // Skip me

View File

@ -59,6 +59,7 @@ import org.elasticsearch.script.ScriptService;
import org.elasticsearch.search.SearchModule; import org.elasticsearch.search.SearchModule;
import org.elasticsearch.search.SearchRequestParsers; import org.elasticsearch.search.SearchRequestParsers;
import org.elasticsearch.search.aggregations.AggregationBuilders; import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.fetch.FetchSubPhasePluginIT;
import org.elasticsearch.search.fetch.subphase.FetchSourceContext; import org.elasticsearch.search.fetch.subphase.FetchSourceContext;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilderTests; import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilderTests;
import org.elasticsearch.search.rescore.QueryRescoreBuilderTests; import org.elasticsearch.search.rescore.QueryRescoreBuilderTests;
@ -85,7 +86,6 @@ import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import static java.util.Collections.emptyList;
import static org.elasticsearch.test.ClusterServiceUtils.createClusterService; import static org.elasticsearch.test.ClusterServiceUtils.createClusterService;
import static org.elasticsearch.test.ClusterServiceUtils.setState; import static org.elasticsearch.test.ClusterServiceUtils.setState;
import static org.hamcrest.CoreMatchers.containsString; import static org.hamcrest.CoreMatchers.containsString;
@ -132,7 +132,8 @@ public class SearchSourceBuilderTests extends ESTestCase {
bindMapperExtension(); bindMapperExtension();
} }
}; };
SearchModule searchModule = new SearchModule(settings, false, emptyList()) { SearchModule searchModule = new SearchModule(settings, false,
Collections.singletonList(new FetchSubPhasePluginIT.FetchTermVectorsPlugin())) {
@Override @Override
protected void configureSearch() { protected void configureSearch() {
// Skip me // Skip me
@ -389,11 +390,7 @@ public class SearchSourceBuilderTests extends ESTestCase {
builder.aggregation(AggregationBuilders.avg(randomAsciiOfLengthBetween(5, 20))); builder.aggregation(AggregationBuilders.avg(randomAsciiOfLengthBetween(5, 20)));
} }
if (randomBoolean()) { if (randomBoolean()) {
XContentBuilder xContentBuilder = XContentFactory.jsonBuilder(); builder.ext(Collections.singletonList(new FetchSubPhasePluginIT.TermVectorsFetchBuilder("test")));
xContentBuilder.startObject();
xContentBuilder.field("term_vectors_fetch", randomAsciiOfLengthBetween(5, 20));
xContentBuilder.endObject();
builder.ext(xContentBuilder);
} }
if (randomBoolean()) { if (randomBoolean()) {
String field = randomBoolean() ? null : randomAsciiOfLengthBetween(5, 20); String field = randomBoolean() ? null : randomAsciiOfLengthBetween(5, 20);
@ -431,15 +428,14 @@ public class SearchSourceBuilderTests extends ESTestCase {
// test the embedded case // test the embedded case
} }
SearchSourceBuilder newBuilder = SearchSourceBuilder.fromXContent(parseContext, searchRequestParsers.aggParsers, SearchSourceBuilder newBuilder = SearchSourceBuilder.fromXContent(parseContext, searchRequestParsers.aggParsers,
searchRequestParsers.suggesters); searchRequestParsers.suggesters, searchRequestParsers.searchExtParsers);
assertNull(parser.nextToken()); assertNull(parser.nextToken());
assertEquals(testBuilder, newBuilder); assertEquals(testBuilder, newBuilder);
assertEquals(testBuilder.hashCode(), newBuilder.hashCode()); assertEquals(testBuilder.hashCode(), newBuilder.hashCode());
} }
private static QueryParseContext createParseContext(XContentParser parser) { private static QueryParseContext createParseContext(XContentParser parser) {
QueryParseContext context = new QueryParseContext(searchRequestParsers.queryParsers, parser, parseFieldMatcher); return new QueryParseContext(searchRequestParsers.queryParsers, parser, parseFieldMatcher);
return context;
} }
public void testSerialization() throws IOException { public void testSerialization() throws IOException {
@ -497,7 +493,7 @@ public class SearchSourceBuilderTests extends ESTestCase {
String restContent = " { \"_source\": { \"includes\": \"include\", \"excludes\": \"*.field2\"}}"; String restContent = " { \"_source\": { \"includes\": \"include\", \"excludes\": \"*.field2\"}}";
try (XContentParser parser = XContentFactory.xContent(restContent).createParser(restContent)) { try (XContentParser parser = XContentFactory.xContent(restContent).createParser(restContent)) {
SearchSourceBuilder searchSourceBuilder = SearchSourceBuilder.fromXContent(createParseContext(parser), SearchSourceBuilder searchSourceBuilder = SearchSourceBuilder.fromXContent(createParseContext(parser),
searchRequestParsers.aggParsers, searchRequestParsers.suggesters); searchRequestParsers.aggParsers, searchRequestParsers.suggesters, searchRequestParsers.searchExtParsers);
assertArrayEquals(new String[]{"*.field2"}, searchSourceBuilder.fetchSource().excludes()); assertArrayEquals(new String[]{"*.field2"}, searchSourceBuilder.fetchSource().excludes());
assertArrayEquals(new String[]{"include"}, searchSourceBuilder.fetchSource().includes()); assertArrayEquals(new String[]{"include"}, searchSourceBuilder.fetchSource().includes());
} }
@ -506,7 +502,7 @@ public class SearchSourceBuilderTests extends ESTestCase {
String restContent = " { \"_source\": false}"; String restContent = " { \"_source\": false}";
try (XContentParser parser = XContentFactory.xContent(restContent).createParser(restContent)) { try (XContentParser parser = XContentFactory.xContent(restContent).createParser(restContent)) {
SearchSourceBuilder searchSourceBuilder = SearchSourceBuilder.fromXContent(createParseContext(parser), SearchSourceBuilder searchSourceBuilder = SearchSourceBuilder.fromXContent(createParseContext(parser),
searchRequestParsers.aggParsers, searchRequestParsers.suggesters); searchRequestParsers.aggParsers, searchRequestParsers.suggesters, searchRequestParsers.searchExtParsers);
assertArrayEquals(new String[]{}, searchSourceBuilder.fetchSource().excludes()); assertArrayEquals(new String[]{}, searchSourceBuilder.fetchSource().excludes());
assertArrayEquals(new String[]{}, searchSourceBuilder.fetchSource().includes()); assertArrayEquals(new String[]{}, searchSourceBuilder.fetchSource().includes());
assertFalse(searchSourceBuilder.fetchSource().fetchSource()); assertFalse(searchSourceBuilder.fetchSource().fetchSource());
@ -519,7 +515,7 @@ public class SearchSourceBuilderTests extends ESTestCase {
String restContent = " { \"sort\": \"foo\"}"; String restContent = " { \"sort\": \"foo\"}";
try (XContentParser parser = XContentFactory.xContent(restContent).createParser(restContent)) { try (XContentParser parser = XContentFactory.xContent(restContent).createParser(restContent)) {
SearchSourceBuilder searchSourceBuilder = SearchSourceBuilder.fromXContent(createParseContext(parser), SearchSourceBuilder searchSourceBuilder = SearchSourceBuilder.fromXContent(createParseContext(parser),
searchRequestParsers.aggParsers, searchRequestParsers.suggesters); searchRequestParsers.aggParsers, searchRequestParsers.suggesters, searchRequestParsers.searchExtParsers);
assertEquals(1, searchSourceBuilder.sorts().size()); assertEquals(1, searchSourceBuilder.sorts().size());
assertEquals(new FieldSortBuilder("foo"), searchSourceBuilder.sorts().get(0)); assertEquals(new FieldSortBuilder("foo"), searchSourceBuilder.sorts().get(0));
} }
@ -535,7 +531,7 @@ public class SearchSourceBuilderTests extends ESTestCase {
" ]}"; " ]}";
try (XContentParser parser = XContentFactory.xContent(restContent).createParser(restContent)) { try (XContentParser parser = XContentFactory.xContent(restContent).createParser(restContent)) {
SearchSourceBuilder searchSourceBuilder = SearchSourceBuilder.fromXContent(createParseContext(parser), SearchSourceBuilder searchSourceBuilder = SearchSourceBuilder.fromXContent(createParseContext(parser),
searchRequestParsers.aggParsers, searchRequestParsers.suggesters); searchRequestParsers.aggParsers, searchRequestParsers.suggesters, searchRequestParsers.searchExtParsers);
assertEquals(5, searchSourceBuilder.sorts().size()); assertEquals(5, searchSourceBuilder.sorts().size());
assertEquals(new FieldSortBuilder("post_date"), searchSourceBuilder.sorts().get(0)); assertEquals(new FieldSortBuilder("post_date"), searchSourceBuilder.sorts().get(0));
assertEquals(new FieldSortBuilder("user"), searchSourceBuilder.sorts().get(1)); assertEquals(new FieldSortBuilder("user"), searchSourceBuilder.sorts().get(1));
@ -559,7 +555,7 @@ public class SearchSourceBuilderTests extends ESTestCase {
"}\n"; "}\n";
try (XContentParser parser = XContentFactory.xContent(restContent).createParser(restContent)) { try (XContentParser parser = XContentFactory.xContent(restContent).createParser(restContent)) {
SearchSourceBuilder searchSourceBuilder = SearchSourceBuilder.fromXContent(createParseContext(parser), SearchSourceBuilder searchSourceBuilder = SearchSourceBuilder.fromXContent(createParseContext(parser),
searchRequestParsers.aggParsers, searchRequestParsers.suggesters); searchRequestParsers.aggParsers, searchRequestParsers.suggesters, searchRequestParsers.searchExtParsers);
assertEquals(1, searchSourceBuilder.aggregations().count()); assertEquals(1, searchSourceBuilder.aggregations().count());
} }
} }
@ -575,7 +571,7 @@ public class SearchSourceBuilderTests extends ESTestCase {
"}\n"; "}\n";
try (XContentParser parser = XContentFactory.xContent(restContent).createParser(restContent)) { try (XContentParser parser = XContentFactory.xContent(restContent).createParser(restContent)) {
SearchSourceBuilder searchSourceBuilder = SearchSourceBuilder.fromXContent(createParseContext(parser), SearchSourceBuilder searchSourceBuilder = SearchSourceBuilder.fromXContent(createParseContext(parser),
searchRequestParsers.aggParsers, searchRequestParsers.suggesters); searchRequestParsers.aggParsers, searchRequestParsers.suggesters, searchRequestParsers.searchExtParsers);
assertEquals(1, searchSourceBuilder.aggregations().count()); assertEquals(1, searchSourceBuilder.aggregations().count());
} }
} }
@ -601,7 +597,7 @@ public class SearchSourceBuilderTests extends ESTestCase {
"}\n"; "}\n";
try (XContentParser parser = XContentFactory.xContent(restContent).createParser(restContent)) { try (XContentParser parser = XContentFactory.xContent(restContent).createParser(restContent)) {
SearchSourceBuilder searchSourceBuilder = SearchSourceBuilder.fromXContent(createParseContext(parser), SearchSourceBuilder searchSourceBuilder = SearchSourceBuilder.fromXContent(createParseContext(parser),
searchRequestParsers.aggParsers, searchRequestParsers.suggesters); searchRequestParsers.aggParsers, searchRequestParsers.suggesters, searchRequestParsers.searchExtParsers);
assertEquals(1, searchSourceBuilder.rescores().size()); assertEquals(1, searchSourceBuilder.rescores().size());
assertEquals(new QueryRescorerBuilder(QueryBuilders.matchQuery("content", "baz")).windowSize(50), assertEquals(new QueryRescorerBuilder(QueryBuilders.matchQuery("content", "baz")).windowSize(50),
searchSourceBuilder.rescores().get(0)); searchSourceBuilder.rescores().get(0));
@ -624,7 +620,7 @@ public class SearchSourceBuilderTests extends ESTestCase {
"}\n"; "}\n";
try (XContentParser parser = XContentFactory.xContent(restContent).createParser(restContent)) { try (XContentParser parser = XContentFactory.xContent(restContent).createParser(restContent)) {
SearchSourceBuilder searchSourceBuilder = SearchSourceBuilder.fromXContent(createParseContext(parser), SearchSourceBuilder searchSourceBuilder = SearchSourceBuilder.fromXContent(createParseContext(parser),
searchRequestParsers.aggParsers, searchRequestParsers.suggesters); searchRequestParsers.aggParsers, searchRequestParsers.suggesters, searchRequestParsers.searchExtParsers);
assertEquals(1, searchSourceBuilder.rescores().size()); assertEquals(1, searchSourceBuilder.rescores().size());
assertEquals(new QueryRescorerBuilder(QueryBuilders.matchQuery("content", "baz")).windowSize(50), assertEquals(new QueryRescorerBuilder(QueryBuilders.matchQuery("content", "baz")).windowSize(50),
searchSourceBuilder.rescores().get(0)); searchSourceBuilder.rescores().get(0));
@ -637,7 +633,7 @@ public class SearchSourceBuilderTests extends ESTestCase {
final String query = "{ \"query\": { \"match_all\": {}}, \"timeout\": \"" + timeout + "\"}"; final String query = "{ \"query\": { \"match_all\": {}}, \"timeout\": \"" + timeout + "\"}";
try (XContentParser parser = XContentFactory.xContent(query).createParser(query)) { try (XContentParser parser = XContentFactory.xContent(query).createParser(query)) {
final SearchSourceBuilder builder = SearchSourceBuilder.fromXContent(createParseContext(parser), final SearchSourceBuilder builder = SearchSourceBuilder.fromXContent(createParseContext(parser),
searchRequestParsers.aggParsers, searchRequestParsers.suggesters); searchRequestParsers.aggParsers, searchRequestParsers.suggesters, searchRequestParsers.searchExtParsers);
assertThat(builder.timeout(), equalTo(TimeValue.parseTimeValue(timeout, null, "timeout"))); assertThat(builder.timeout(), equalTo(TimeValue.parseTimeValue(timeout, null, "timeout")));
} }
} }
@ -650,7 +646,7 @@ public class SearchSourceBuilderTests extends ESTestCase {
expectThrows( expectThrows(
ElasticsearchParseException.class, ElasticsearchParseException.class,
() -> SearchSourceBuilder.fromXContent(createParseContext(parser), () -> SearchSourceBuilder.fromXContent(createParseContext(parser),
searchRequestParsers.aggParsers, searchRequestParsers.suggesters)); searchRequestParsers.aggParsers, searchRequestParsers.suggesters, searchRequestParsers.searchExtParsers));
assertThat(e, hasToString(containsString("unit is missing or unrecognized"))); assertThat(e, hasToString(containsString("unit is missing or unrecognized")));
} }
} }

View File

@ -27,12 +27,15 @@ import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.termvectors.TermVectorsRequest; import org.elasticsearch.action.termvectors.TermVectorsRequest;
import org.elasticsearch.action.termvectors.TermVectorsResponse; import org.elasticsearch.action.termvectors.TermVectorsResponse;
import org.elasticsearch.common.ParsingException; import org.elasticsearch.common.ParsingException;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.logging.ESLoggerFactory; import org.elasticsearch.common.logging.ESLoggerFactory;
import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.index.termvectors.TermVectorsService; import org.elasticsearch.index.termvectors.TermVectorsService;
import org.elasticsearch.plugins.Plugin; import org.elasticsearch.plugins.Plugin;
import org.elasticsearch.plugins.SearchPlugin; import org.elasticsearch.plugins.SearchPlugin;
import org.elasticsearch.search.SearchExtBuilder;
import org.elasticsearch.search.SearchExtParser; import org.elasticsearch.search.SearchExtParser;
import org.elasticsearch.search.SearchHitField; import org.elasticsearch.search.SearchHitField;
import org.elasticsearch.search.builder.SearchSourceBuilder; import org.elasticsearch.search.builder.SearchSourceBuilder;
@ -49,6 +52,7 @@ import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects;
import static java.util.Collections.singletonList; import static java.util.Collections.singletonList;
import static org.elasticsearch.client.Requests.indexRequest; import static org.elasticsearch.client.Requests.indexRequest;
@ -56,13 +60,18 @@ import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertSearchResponse; import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertSearchResponse;
import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.equalTo;
@ClusterScope(scope = Scope.SUITE, supportsDedicatedMasters = false, numDataNodes = 1) @ClusterScope(scope = Scope.SUITE, supportsDedicatedMasters = false, numDataNodes = 2)
public class FetchSubPhasePluginIT extends ESIntegTestCase { public class FetchSubPhasePluginIT extends ESIntegTestCase {
@Override @Override
protected Collection<Class<? extends Plugin>> nodePlugins() { protected Collection<Class<? extends Plugin>> nodePlugins() {
return Collections.singletonList(FetchTermVectorsPlugin.class); return Collections.singletonList(FetchTermVectorsPlugin.class);
} }
@Override
protected Collection<Class<? extends Plugin>> transportClientPlugins() {
return nodePlugins();
}
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public void testPlugin() throws Exception { public void testPlugin() throws Exception {
client().admin() client().admin()
@ -85,10 +94,8 @@ public class FetchSubPhasePluginIT extends ESIntegTestCase {
client().admin().indices().prepareRefresh().execute().actionGet(); client().admin().indices().prepareRefresh().execute().actionGet();
XContentBuilder extSource = jsonBuilder().startObject() SearchResponse response = client().prepareSearch().setSource(new SearchSourceBuilder()
.field("term_vectors_fetch", "test") .ext(Collections.singletonList(new TermVectorsFetchBuilder("test")))).get();
.endObject();
SearchResponse response = client().prepareSearch().setSource(new SearchSourceBuilder().ext(extSource)).get();
assertSearchResponse(response); assertSearchResponse(response);
assertThat(((Map<String, Integer>) response.getHits().getAt(0).field("term_vectors_fetch").getValues().get(0)).get("i"), assertThat(((Map<String, Integer>) response.getHits().getAt(0).field("term_vectors_fetch").getValues().get(0)).get("i"),
equalTo(2)); equalTo(2));
@ -105,8 +112,9 @@ public class FetchSubPhasePluginIT extends ESIntegTestCase {
} }
@Override @Override
public List<SearchExtParser> getSearchExtParsers() { public List<SearchExtSpec<?>> getSearchExts() {
return Collections.singletonList(TermVectorsFetchParser.INSTANCE); return Collections.singletonList(new SearchExtSpec<>(TermVectorsFetchSubPhase.NAME,
TermVectorsFetchBuilder::new, TermVectorsFetchParser.INSTANCE));
} }
} }
@ -115,7 +123,7 @@ public class FetchSubPhasePluginIT extends ESIntegTestCase {
@Override @Override
public void hitExecute(SearchContext context, HitContext hitContext) { public void hitExecute(SearchContext context, HitContext hitContext) {
TermVectorsFetchBuilder fetchSubPhaseBuilder = (TermVectorsFetchBuilder)context.getSearchExtBuilder(NAME); TermVectorsFetchBuilder fetchSubPhaseBuilder = (TermVectorsFetchBuilder)context.getSearchExt(NAME);
if (fetchSubPhaseBuilder == null) { if (fetchSubPhaseBuilder == null) {
return; return;
} }
@ -145,7 +153,7 @@ public class FetchSubPhasePluginIT extends ESIntegTestCase {
} }
} }
public static final class TermVectorsFetchParser implements SearchExtParser { public static final class TermVectorsFetchParser implements SearchExtParser<TermVectorsFetchBuilder> {
private static final TermVectorsFetchParser INSTANCE = new TermVectorsFetchParser(); private static final TermVectorsFetchParser INSTANCE = new TermVectorsFetchParser();
@ -153,12 +161,7 @@ public class FetchSubPhasePluginIT extends ESIntegTestCase {
} }
@Override @Override
public String getName() { public TermVectorsFetchBuilder fromXContent(XContentParser parser) throws IOException {
return TermVectorsFetchSubPhase.NAME;
}
@Override
public TermVectorsFetchBuilder parse(XContentParser parser) throws Exception {
String field; String field;
XContentParser.Token token = parser.currentToken(); XContentParser.Token token = parser.currentToken();
if (token == XContentParser.Token.VALUE_STRING) { if (token == XContentParser.Token.VALUE_STRING) {
@ -173,15 +176,51 @@ public class FetchSubPhasePluginIT extends ESIntegTestCase {
} }
} }
public static final class TermVectorsFetchBuilder { public static final class TermVectorsFetchBuilder extends SearchExtBuilder {
private final String field; private final String field;
private TermVectorsFetchBuilder(String field) { public TermVectorsFetchBuilder(String field) {
this.field = field; this.field = field;
} }
public TermVectorsFetchBuilder(StreamInput in) throws IOException {
this.field = in.readString();
}
public String getField() { public String getField() {
return field; return field;
} }
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
TermVectorsFetchBuilder that = (TermVectorsFetchBuilder) o;
return Objects.equals(field, that.field);
}
@Override
public int hashCode() {
return Objects.hash(field);
}
@Override
public String getWriteableName() {
return TermVectorsFetchSubPhase.NAME;
}
@Override
public void writeTo(StreamOutput out) throws IOException {
out.writeString(field);
}
@Override
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
return builder.field(TermVectorsFetchSubPhase.NAME, field);
}
} }
} }

View File

@ -34,12 +34,14 @@ import org.elasticsearch.index.shard.ShardId;
import org.elasticsearch.indices.IndicesModule; import org.elasticsearch.indices.IndicesModule;
import org.elasticsearch.search.SearchModule; import org.elasticsearch.search.SearchModule;
import org.elasticsearch.search.SearchRequestTests; import org.elasticsearch.search.SearchRequestTests;
import org.elasticsearch.search.fetch.FetchSubPhasePluginIT;
import org.elasticsearch.test.ESTestCase; import org.elasticsearch.test.ESTestCase;
import org.junit.AfterClass; import org.junit.AfterClass;
import org.junit.BeforeClass; import org.junit.BeforeClass;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.List; import java.util.List;
import static java.util.Collections.emptyList; import static java.util.Collections.emptyList;
@ -56,7 +58,8 @@ public class ShardSearchTransportRequestTests extends ESTestCase {
bindMapperExtension(); bindMapperExtension();
} }
}; };
SearchModule searchModule = new SearchModule(Settings.EMPTY, false, emptyList()) { SearchModule searchModule = new SearchModule(Settings.EMPTY, false,
Collections.singletonList(new FetchSubPhasePluginIT.FetchTermVectorsPlugin())) {
@Override @Override
protected void configureSearch() { protected void configureSearch() {
// Skip me // Skip me

View File

@ -32,14 +32,11 @@ import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentFactory; import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.index.query.QueryParseContext; import org.elasticsearch.index.query.QueryParseContext;
import org.elasticsearch.indices.query.IndicesQueriesRegistry;
import org.elasticsearch.script.ExecutableScript; import org.elasticsearch.script.ExecutableScript;
import org.elasticsearch.script.Script; import org.elasticsearch.script.Script;
import org.elasticsearch.script.ScriptService; import org.elasticsearch.script.ScriptService;
import org.elasticsearch.search.SearchRequestParsers; import org.elasticsearch.search.SearchRequestParsers;
import org.elasticsearch.search.aggregations.AggregatorParsers;
import org.elasticsearch.search.builder.SearchSourceBuilder; import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.suggest.Suggesters;
import org.elasticsearch.threadpool.ThreadPool; import org.elasticsearch.threadpool.ThreadPool;
import org.elasticsearch.transport.TransportService; import org.elasticsearch.transport.TransportService;
@ -86,7 +83,7 @@ public class TransportSearchTemplateAction extends HandledTransportAction<Search
try (XContentParser parser = XContentFactory.xContent(source).createParser(source)) { try (XContentParser parser = XContentFactory.xContent(source).createParser(source)) {
SearchSourceBuilder builder = SearchSourceBuilder.searchSource(); SearchSourceBuilder builder = SearchSourceBuilder.searchSource();
builder.parseXContent(new QueryParseContext(searchRequestParsers.queryParsers, parser, parseFieldMatcher), builder.parseXContent(new QueryParseContext(searchRequestParsers.queryParsers, parser, parseFieldMatcher),
searchRequestParsers.aggParsers, searchRequestParsers.suggesters); searchRequestParsers.aggParsers, searchRequestParsers.suggesters, searchRequestParsers.searchExtParsers);
searchRequest.source(builder); searchRequest.source(builder);
searchAction.execute(searchRequest, new ActionListener<SearchResponse>() { searchAction.execute(searchRequest, new ActionListener<SearchResponse>() {

View File

@ -37,9 +37,7 @@ import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.collect.Tuple; import org.elasticsearch.common.collect.Tuple;
import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.indices.query.IndicesQueriesRegistry;
import org.elasticsearch.search.SearchRequestParsers; import org.elasticsearch.search.SearchRequestParsers;
import org.elasticsearch.search.aggregations.AggregatorParsers;
import org.elasticsearch.threadpool.ThreadPool; import org.elasticsearch.threadpool.ThreadPool;
import org.elasticsearch.transport.TransportService; import org.elasticsearch.transport.TransportService;
@ -160,8 +158,7 @@ public class TransportMultiPercolateAction extends HandledTransportAction<MultiP
try { try {
SearchRequest searchRequest = TransportPercolateAction.createSearchRequest( SearchRequest searchRequest = TransportPercolateAction.createSearchRequest(
percolateRequest, docSource, searchRequestParsers.queryParsers, percolateRequest, docSource, searchRequestParsers.queryParsers,
searchRequestParsers.aggParsers, parseFieldMatcher searchRequestParsers.aggParsers, searchRequestParsers.searchExtParsers, parseFieldMatcher);
);
multiSearchRequest.add(searchRequest); multiSearchRequest.add(searchRequest);
} catch (Exception e) { } catch (Exception e) {
preFailures.put(i, new MultiPercolateResponse.Item(e)); preFailures.put(i, new MultiPercolateResponse.Item(e));

View File

@ -45,6 +45,7 @@ import org.elasticsearch.index.query.ConstantScoreQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders; import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.QueryParseContext; import org.elasticsearch.index.query.QueryParseContext;
import org.elasticsearch.indices.query.IndicesQueriesRegistry; import org.elasticsearch.indices.query.IndicesQueriesRegistry;
import org.elasticsearch.search.SearchExtRegistry;
import org.elasticsearch.search.SearchHit; import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits; import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.SearchRequestParsers; import org.elasticsearch.search.SearchRequestParsers;
@ -69,7 +70,8 @@ public class TransportPercolateAction extends HandledTransportAction<PercolateRe
public TransportPercolateAction(Settings settings, ThreadPool threadPool, TransportService transportService, public TransportPercolateAction(Settings settings, ThreadPool threadPool, TransportService transportService,
ActionFilters actionFilters, IndexNameExpressionResolver indexNameExpressionResolver, ActionFilters actionFilters, IndexNameExpressionResolver indexNameExpressionResolver,
Client client, SearchRequestParsers searchRequestParsers) { Client client, SearchRequestParsers searchRequestParsers) {
super(settings, PercolateAction.NAME, threadPool, transportService, actionFilters, indexNameExpressionResolver, PercolateRequest::new); super(settings, PercolateAction.NAME, threadPool, transportService, actionFilters,
indexNameExpressionResolver, PercolateRequest::new);
this.client = client; this.client = client;
this.searchRequestParsers = searchRequestParsers; this.searchRequestParsers = searchRequestParsers;
this.parseFieldMatcher = new ParseFieldMatcher(settings); this.parseFieldMatcher = new ParseFieldMatcher(settings);
@ -84,7 +86,8 @@ public class TransportPercolateAction extends HandledTransportAction<PercolateRe
if (getResponse.isExists()) { if (getResponse.isExists()) {
innerDoExecute(request, getResponse.getSourceAsBytesRef(), listener); innerDoExecute(request, getResponse.getSourceAsBytesRef(), listener);
} else { } else {
onFailure(new ResourceNotFoundException("percolate document [{}/{}/{}] doesn't exist", request.getRequest().index(), request.getRequest().type(), request.getRequest().id())); onFailure(new ResourceNotFoundException("percolate document [{}/{}/{}] doesn't exist",
request.getRequest().index(), request.getRequest().type(), request.getRequest().id()));
} }
} }
@ -102,7 +105,7 @@ public class TransportPercolateAction extends HandledTransportAction<PercolateRe
SearchRequest searchRequest; SearchRequest searchRequest;
try { try {
searchRequest = createSearchRequest(request, docSource, searchRequestParsers.queryParsers, searchRequest = createSearchRequest(request, docSource, searchRequestParsers.queryParsers,
searchRequestParsers.aggParsers, parseFieldMatcher); searchRequestParsers.aggParsers, searchRequestParsers.searchExtParsers, parseFieldMatcher);
} catch (IOException e) { } catch (IOException e) {
listener.onFailure(e); listener.onFailure(e);
return; return;
@ -124,7 +127,10 @@ public class TransportPercolateAction extends HandledTransportAction<PercolateRe
}); });
} }
public static SearchRequest createSearchRequest(PercolateRequest percolateRequest, BytesReference documentSource, IndicesQueriesRegistry queryRegistry, AggregatorParsers aggParsers, ParseFieldMatcher parseFieldMatcher) throws IOException { public static SearchRequest createSearchRequest(PercolateRequest percolateRequest, BytesReference documentSource,
IndicesQueriesRegistry queryRegistry, AggregatorParsers aggParsers,
SearchExtRegistry searchExtRegistry, ParseFieldMatcher parseFieldMatcher)
throws IOException {
SearchRequest searchRequest = new SearchRequest(); SearchRequest searchRequest = new SearchRequest();
if (percolateRequest.indices() != null) { if (percolateRequest.indices() != null) {
searchRequest.indices(percolateRequest.indices()); searchRequest.indices(percolateRequest.indices());
@ -220,7 +226,7 @@ public class TransportPercolateAction extends HandledTransportAction<PercolateRe
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
try (XContentParser parser = XContentFactory.xContent(XContentType.JSON).createParser(source)) { try (XContentParser parser = XContentFactory.xContent(XContentType.JSON).createParser(source)) {
QueryParseContext context = new QueryParseContext(queryRegistry, parser, parseFieldMatcher); QueryParseContext context = new QueryParseContext(queryRegistry, parser, parseFieldMatcher);
searchSourceBuilder.parseXContent(context, aggParsers, null); searchSourceBuilder.parseXContent(context, aggParsers, null, searchExtRegistry);
searchRequest.source(searchSourceBuilder); searchRequest.source(searchSourceBuilder);
return searchRequest; return searchRequest;
} }
@ -235,7 +241,8 @@ public class TransportPercolateAction extends HandledTransportAction<PercolateRe
matches = new PercolateResponse.Match[hits.getHits().length]; matches = new PercolateResponse.Match[hits.getHits().length];
for (int i = 0; i < hits.getHits().length; i++) { for (int i = 0; i < hits.getHits().length; i++) {
SearchHit hit = hits.getHits()[i]; SearchHit hit = hits.getHits()[i];
matches[i] = new PercolateResponse.Match(new Text(hit.getIndex()), new Text(hit.getId()), hit.getScore(), hit.getHighlightFields()); matches[i] = new PercolateResponse.Match(new Text(hit.getIndex()),
new Text(hit.getId()), hit.getScore(), hit.getHighlightFields());
} }
} }
@ -246,8 +253,8 @@ public class TransportPercolateAction extends HandledTransportAction<PercolateRe
} }
return new PercolateResponse( return new PercolateResponse(
searchResponse.getTotalShards(), searchResponse.getSuccessfulShards(), searchResponse.getFailedShards(), searchResponse.getTotalShards(), searchResponse.getSuccessfulShards(), searchResponse.getFailedShards(), shardFailures,
shardFailures, matches, hits.getTotalHits(), searchResponse.getTookInMillis(), (InternalAggregations) searchResponse.getAggregations() matches, hits.getTotalHits(), searchResponse.getTookInMillis(), (InternalAggregations) searchResponse.getAggregations()
); );
} }

View File

@ -42,14 +42,11 @@ import org.elasticsearch.common.xcontent.json.JsonXContent;
import org.elasticsearch.index.VersionType; import org.elasticsearch.index.VersionType;
import org.elasticsearch.index.query.QueryParseContext; import org.elasticsearch.index.query.QueryParseContext;
import org.elasticsearch.index.reindex.remote.RemoteInfo; import org.elasticsearch.index.reindex.remote.RemoteInfo;
import org.elasticsearch.indices.query.IndicesQueriesRegistry;
import org.elasticsearch.rest.RestChannel; import org.elasticsearch.rest.RestChannel;
import org.elasticsearch.rest.RestController; import org.elasticsearch.rest.RestController;
import org.elasticsearch.rest.RestRequest; import org.elasticsearch.rest.RestRequest;
import org.elasticsearch.script.Script; import org.elasticsearch.script.Script;
import org.elasticsearch.search.SearchRequestParsers; import org.elasticsearch.search.SearchRequestParsers;
import org.elasticsearch.search.aggregations.AggregatorParsers;
import org.elasticsearch.search.suggest.Suggesters;
import java.io.IOException; import java.io.IOException;
import java.util.List; import java.util.List;
@ -87,7 +84,8 @@ public class RestReindexAction extends AbstractBaseReindexRestHandler<ReindexReq
builder.map(source); builder.map(source);
try (XContentParser innerParser = parser.contentType().xContent().createParser(builder.bytes())) { try (XContentParser innerParser = parser.contentType().xContent().createParser(builder.bytes())) {
request.getSearchRequest().source().parseXContent(context.queryParseContext(innerParser), request.getSearchRequest().source().parseXContent(context.queryParseContext(innerParser),
context.searchRequestParsers.aggParsers, context.searchRequestParsers.suggesters); context.searchRequestParsers.aggParsers, context.searchRequestParsers.suggesters,
context.searchRequestParsers.searchExtParsers);
} }
}; };

View File

@ -110,7 +110,7 @@ public class RestReindexActionTests extends ESTestCase {
} }
try (XContentParser p = JsonXContent.jsonXContent.createParser(request)) { try (XContentParser p = JsonXContent.jsonXContent.createParser(request)) {
ReindexRequest r = new ReindexRequest(new SearchRequest(), new IndexRequest()); ReindexRequest r = new ReindexRequest(new SearchRequest(), new IndexRequest());
SearchRequestParsers searchParsers = new SearchRequestParsers(new IndicesQueriesRegistry(), null, null); SearchRequestParsers searchParsers = new SearchRequestParsers(new IndicesQueriesRegistry(), null, null, null);
RestReindexAction.PARSER.parse(p, r, new ReindexParseContext(searchParsers, ParseFieldMatcher.STRICT)); RestReindexAction.PARSER.parse(p, r, new ReindexParseContext(searchParsers, ParseFieldMatcher.STRICT));
assertEquals("localhost", r.getRemoteInfo().getHost()); assertEquals("localhost", r.getRemoteInfo().getHost());
assertArrayEquals(new String[] {"source"}, r.getSearchRequest().indices()); assertArrayEquals(new String[] {"source"}, r.getSearchRequest().indices());

View File

@ -72,9 +72,8 @@ public class MockSearchService extends SearchService {
@Inject @Inject
public MockSearchService(Settings settings, ClusterSettings clusterSettings, ClusterService clusterService, public MockSearchService(Settings settings, ClusterSettings clusterSettings, ClusterService clusterService,
IndicesService indicesService, ThreadPool threadPool, ScriptService scriptService, IndicesService indicesService, ThreadPool threadPool, ScriptService scriptService,
BigArrays bigArrays, FetchPhase fetchPhase, SearchExtParserRegistry searchExtParserRegistry) { BigArrays bigArrays, FetchPhase fetchPhase) {
super(settings, clusterSettings, clusterService, indicesService, threadPool, scriptService, super(settings, clusterSettings, clusterService, indicesService, threadPool, scriptService, bigArrays, fetchPhase);
bigArrays, fetchPhase, searchExtParserRegistry);
} }
@Override @Override

View File

@ -39,6 +39,7 @@ import org.elasticsearch.index.query.QueryShardContext;
import org.elasticsearch.index.shard.IndexShard; import org.elasticsearch.index.shard.IndexShard;
import org.elasticsearch.index.similarity.SimilarityService; import org.elasticsearch.index.similarity.SimilarityService;
import org.elasticsearch.script.ScriptService; import org.elasticsearch.script.ScriptService;
import org.elasticsearch.search.SearchExtBuilder;
import org.elasticsearch.search.SearchShardTarget; import org.elasticsearch.search.SearchShardTarget;
import org.elasticsearch.search.aggregations.SearchContextAggregations; import org.elasticsearch.search.aggregations.SearchContextAggregations;
import org.elasticsearch.search.dfs.DfsSearchResult; import org.elasticsearch.search.dfs.DfsSearchResult;
@ -89,7 +90,7 @@ public class TestSearchContext extends SearchContext {
private SearchContextAggregations aggregations; private SearchContextAggregations aggregations;
private final long originNanoTime = System.nanoTime(); private final long originNanoTime = System.nanoTime();
private final Map<String, Object> searchExtBuilders = new HashMap<>(); private final Map<String, SearchExtBuilder> searchExtBuilders = new HashMap<>();
public TestSearchContext(ThreadPool threadPool, BigArrays bigArrays, ScriptService scriptService, IndexService indexService) { public TestSearchContext(ThreadPool threadPool, BigArrays bigArrays, ScriptService scriptService, IndexService indexService) {
super(ParseFieldMatcher.STRICT); super(ParseFieldMatcher.STRICT);
@ -196,12 +197,12 @@ public class TestSearchContext extends SearchContext {
} }
@Override @Override
public void putSearchExtBuilder(String name, Object searchExtBuilders) { public void addSearchExt(SearchExtBuilder searchExtBuilder) {
this.searchExtBuilders.put(name, searchExtBuilders); searchExtBuilders.put(searchExtBuilder.getWriteableName(), searchExtBuilder);
} }
@Override @Override
public Object getSearchExtBuilder(String name) { public SearchExtBuilder getSearchExt(String name) {
return searchExtBuilders.get(name); return searchExtBuilders.get(name);
} }