From 82638737833b7787df42369de10b5cdfdff1bc38 Mon Sep 17 00:00:00 2001 From: Nik Everett Date: Sun, 3 Jul 2016 14:41:47 -0400 Subject: [PATCH] Switch search extension from push to pull Switches most search behavior extensions from push (`onModule(SearchModule)`) to pull (`implements SearchPlugin`). This effort in general gives plugin authors a much cleaner view of how to extend Elasticsearch and starts to set up portions of Elasticsearch as "the plugin API". This commit in particular does that for search-time behavior like customized suggesters, highlighters, score functions, and significance heuristics. It also switches most such customization to being done at search module construction time which is much, much easier to reason about from a testing perspective. It also helps significantly in the process of de-guice-ing Elasticsearch's startup. There are at least two major search time extensions that aren't covered in this commit that will simply have to wait for the next commit on the topic because this one has already grown large: custom aggregations and custom queries. These will likely live in the same SearchPlugin interface as well. --- .../client/transport/TransportClient.java | 3 +- .../functionscore/DecayFunctionParser.java | 6 +- .../ExponentialDecayFunctionBuilder.java | 2 - .../FieldValueFactorFunctionBuilder.java | 2 - .../LinearDecayFunctionBuilder.java | 2 - .../RandomScoreFunctionBuilder.java | 2 - .../ScriptScoreFunctionBuilder.java | 2 - .../java/org/elasticsearch/node/Node.java | 3 +- .../org/elasticsearch/plugins/Plugin.java | 10 +- .../elasticsearch/plugins/SearchPlugin.java | 177 +++++++++++ .../elasticsearch/search/Highlighters.java | 63 ---- .../elasticsearch/search/SearchModule.java | 278 ++++++++++-------- .../significant/heuristics/ChiSquare.java | 11 +- .../bucket/significant/heuristics/GND.java | 11 +- .../significant/heuristics/JLHScore.java | 9 +- .../heuristics/MutualInformation.java | 13 +- .../heuristics/PercentageScore.java | 9 +- .../heuristics/ScriptHeuristic.java | 10 +- .../heuristics/SignificanceHeuristic.java | 5 +- .../pipeline/movavg/models/EwmaModel.java | 6 +- .../movavg/models/HoltLinearModel.java | 6 +- .../movavg/models/HoltWintersModel.java | 5 +- .../pipeline/movavg/models/LinearModel.java | 6 +- .../pipeline/movavg/models/SimpleModel.java | 4 +- .../search/fetch/FetchPhase.java | 2 +- .../search/fetch/FetchSubPhase.java | 3 +- .../search/highlight/HighlightPhase.java | 5 +- .../search/highlight/Highlighter.java | 2 +- .../search/suggest/Suggesters.java | 35 +-- .../index/query/InnerHitBuilderTests.java | 4 +- .../FunctionScoreQueryBuilderTests.java | 23 +- .../search/SearchModuleTests.java | 138 ++++++--- .../aggregations/AggregatorParsingTests.java | 3 +- .../aggregations/BaseAggregationTestCase.java | 3 +- .../SignificantTermsSignificanceScoreIT.java | 24 +- .../SignificanceHeuristicTests.java | 5 +- .../builder/SearchSourceBuilderTests.java | 3 +- .../search/fetch/FetchSubPhasePluginIT.java | 12 +- .../functionscore/FunctionScorePluginIT.java | 15 +- .../highlight/CustomHighlighterPlugin.java | 12 +- .../highlight/CustomHighlighterSearchIT.java | 2 +- .../highlight/HighlightBuilderTests.java | 3 +- .../rescore/QueryRescoreBuilderTests.java | 3 +- .../search/sort/AbstractSortTestCase.java | 3 +- .../search/sort/SortBuilderTests.java | 4 +- .../AbstractSuggestionBuilderTestCase.java | 4 +- .../search/suggest/CustomSuggester.java | 2 +- .../search/suggest/CustomSuggesterPlugin.java | 13 +- .../suggest/CustomSuggesterSearchIT.java | 2 +- .../search/suggest/SuggestBuilderTests.java | 6 +- .../phrase/SmoothingModelTestCase.java | 4 +- .../migration/migrate_5_0/plugins.asciidoc | 6 + .../messy/tests/TemplateQueryParserTests.java | 2 +- .../PercolatorHighlightSubFetchPhase.java | 5 +- .../percolator/PercolatorPlugin.java | 12 +- ...PercolatorHighlightSubFetchPhaseTests.java | 4 +- .../test/AbstractQueryTestCase.java | 3 +- .../hamcrest/ElasticsearchAssertions.java | 3 +- 58 files changed, 612 insertions(+), 403 deletions(-) create mode 100644 core/src/main/java/org/elasticsearch/plugins/SearchPlugin.java delete mode 100644 core/src/main/java/org/elasticsearch/search/Highlighters.java diff --git a/core/src/main/java/org/elasticsearch/client/transport/TransportClient.java b/core/src/main/java/org/elasticsearch/client/transport/TransportClient.java index 2affef6dac8..7f7820620f4 100644 --- a/core/src/main/java/org/elasticsearch/client/transport/TransportClient.java +++ b/core/src/main/java/org/elasticsearch/client/transport/TransportClient.java @@ -55,6 +55,7 @@ import org.elasticsearch.node.internal.InternalSettingsPreparer; import org.elasticsearch.plugins.ActionPlugin; import org.elasticsearch.plugins.Plugin; import org.elasticsearch.plugins.PluginsService; +import org.elasticsearch.plugins.SearchPlugin; import org.elasticsearch.search.SearchModule; import org.elasticsearch.threadpool.ExecutorBuilder; import org.elasticsearch.threadpool.ThreadPool; @@ -145,7 +146,7 @@ public class TransportClient extends AbstractClient { } modules.add(new NetworkModule(networkService, settings, true, namedWriteableRegistry)); modules.add(b -> b.bind(ThreadPool.class).toInstance(threadPool)); - modules.add(new SearchModule(settings, namedWriteableRegistry, true)); + modules.add(new SearchModule(settings, namedWriteableRegistry, true, pluginsService.filterPlugins(SearchPlugin.class))); ActionModule actionModule = new ActionModule(false, true, settings, null, settingsModule.getClusterSettings(), pluginsService.filterPlugins(ActionPlugin.class)); modules.add(actionModule); diff --git a/core/src/main/java/org/elasticsearch/index/query/functionscore/DecayFunctionParser.java b/core/src/main/java/org/elasticsearch/index/query/functionscore/DecayFunctionParser.java index 3187e29df11..2c8b9af28d6 100644 --- a/core/src/main/java/org/elasticsearch/index/query/functionscore/DecayFunctionParser.java +++ b/core/src/main/java/org/elasticsearch/index/query/functionscore/DecayFunctionParser.java @@ -22,12 +22,13 @@ package org.elasticsearch.index.query.functionscore; import org.elasticsearch.common.ParseField; import org.elasticsearch.common.ParsingException; import org.elasticsearch.common.bytes.BytesReference; -import org.elasticsearch.common.io.stream.Writeable; 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.plugins.SearchPlugin; import org.elasticsearch.search.MultiValueMode; +import org.elasticsearch.search.SearchModule; import java.io.IOException; import java.util.function.BiFunction; @@ -64,8 +65,7 @@ import java.util.function.BiFunction; *

* To write a new decay scoring function, create a new class that extends * {@link DecayFunctionBuilder}, setup a PARSER field with this class, and - * register them both using - * {@link org.elasticsearch.search.SearchModule#registerScoreFunction(Writeable.Reader, ScoreFunctionParser, ParseField)}. + * register them in {@link SearchModule#registerScoreFunctions} or {@link SearchPlugin#getScoreFunctions} * See {@link GaussDecayFunctionBuilder#PARSER} for an example. */ public final class DecayFunctionParser> implements ScoreFunctionParser { diff --git a/core/src/main/java/org/elasticsearch/index/query/functionscore/ExponentialDecayFunctionBuilder.java b/core/src/main/java/org/elasticsearch/index/query/functionscore/ExponentialDecayFunctionBuilder.java index f4bd3ad1785..c9b7d198d73 100644 --- a/core/src/main/java/org/elasticsearch/index/query/functionscore/ExponentialDecayFunctionBuilder.java +++ b/core/src/main/java/org/elasticsearch/index/query/functionscore/ExponentialDecayFunctionBuilder.java @@ -21,7 +21,6 @@ package org.elasticsearch.index.query.functionscore; import org.apache.lucene.search.Explanation; -import org.elasticsearch.common.ParseField; import org.elasticsearch.common.bytes.BytesReference; import org.elasticsearch.common.io.stream.StreamInput; @@ -29,7 +28,6 @@ import java.io.IOException; public class ExponentialDecayFunctionBuilder extends DecayFunctionBuilder { public static final String NAME = "exp"; - public static final ParseField FUNCTION_NAME_FIELD = new ParseField(NAME); public static final ScoreFunctionParser PARSER = new DecayFunctionParser<>( ExponentialDecayFunctionBuilder::new); public static final DecayFunction EXP_DECAY_FUNCTION = new ExponentialDecayScoreFunction(); diff --git a/core/src/main/java/org/elasticsearch/index/query/functionscore/FieldValueFactorFunctionBuilder.java b/core/src/main/java/org/elasticsearch/index/query/functionscore/FieldValueFactorFunctionBuilder.java index 7f6c5a91d39..d9cef5522ec 100644 --- a/core/src/main/java/org/elasticsearch/index/query/functionscore/FieldValueFactorFunctionBuilder.java +++ b/core/src/main/java/org/elasticsearch/index/query/functionscore/FieldValueFactorFunctionBuilder.java @@ -20,7 +20,6 @@ package org.elasticsearch.index.query.functionscore; import org.elasticsearch.ElasticsearchException; -import org.elasticsearch.common.ParseField; import org.elasticsearch.common.ParsingException; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; @@ -43,7 +42,6 @@ import java.util.Objects; */ public class FieldValueFactorFunctionBuilder extends ScoreFunctionBuilder { public static final String NAME = "field_value_factor"; - public static final ParseField FUNCTION_NAME_FIELD = new ParseField(NAME); public static final FieldValueFactorFunction.Modifier DEFAULT_MODIFIER = FieldValueFactorFunction.Modifier.NONE; public static final float DEFAULT_FACTOR = 1; diff --git a/core/src/main/java/org/elasticsearch/index/query/functionscore/LinearDecayFunctionBuilder.java b/core/src/main/java/org/elasticsearch/index/query/functionscore/LinearDecayFunctionBuilder.java index 613a3572dc0..80895f96343 100644 --- a/core/src/main/java/org/elasticsearch/index/query/functionscore/LinearDecayFunctionBuilder.java +++ b/core/src/main/java/org/elasticsearch/index/query/functionscore/LinearDecayFunctionBuilder.java @@ -20,7 +20,6 @@ package org.elasticsearch.index.query.functionscore; import org.apache.lucene.search.Explanation; -import org.elasticsearch.common.ParseField; import org.elasticsearch.common.bytes.BytesReference; import org.elasticsearch.common.io.stream.StreamInput; @@ -28,7 +27,6 @@ import java.io.IOException; public class LinearDecayFunctionBuilder extends DecayFunctionBuilder { public static final String NAME = "linear"; - public static final ParseField FUNCTION_NAME_FIELD = new ParseField(NAME); public static final ScoreFunctionParser PARSER = new DecayFunctionParser<>(LinearDecayFunctionBuilder::new); public static final DecayFunction LINEAR_DECAY_FUNCTION = new LinearDecayScoreFunction(); diff --git a/core/src/main/java/org/elasticsearch/index/query/functionscore/RandomScoreFunctionBuilder.java b/core/src/main/java/org/elasticsearch/index/query/functionscore/RandomScoreFunctionBuilder.java index fa1f413af8b..4f4a3b54a21 100644 --- a/core/src/main/java/org/elasticsearch/index/query/functionscore/RandomScoreFunctionBuilder.java +++ b/core/src/main/java/org/elasticsearch/index/query/functionscore/RandomScoreFunctionBuilder.java @@ -18,7 +18,6 @@ */ package org.elasticsearch.index.query.functionscore; -import org.elasticsearch.common.ParseField; import org.elasticsearch.common.ParsingException; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; @@ -40,7 +39,6 @@ import java.util.Objects; */ public class RandomScoreFunctionBuilder extends ScoreFunctionBuilder { public static final String NAME = "random_score"; - public static final ParseField FUNCTION_NAME_FIELD = new ParseField(NAME); private Integer seed; public RandomScoreFunctionBuilder() { diff --git a/core/src/main/java/org/elasticsearch/index/query/functionscore/ScriptScoreFunctionBuilder.java b/core/src/main/java/org/elasticsearch/index/query/functionscore/ScriptScoreFunctionBuilder.java index a33a9c14fb7..34b5d58dfa0 100644 --- a/core/src/main/java/org/elasticsearch/index/query/functionscore/ScriptScoreFunctionBuilder.java +++ b/core/src/main/java/org/elasticsearch/index/query/functionscore/ScriptScoreFunctionBuilder.java @@ -19,7 +19,6 @@ package org.elasticsearch.index.query.functionscore; -import org.elasticsearch.common.ParseField; import org.elasticsearch.common.ParsingException; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; @@ -49,7 +48,6 @@ import java.util.Objects; */ public class ScriptScoreFunctionBuilder extends ScoreFunctionBuilder { public static final String NAME = "script_score"; - public static final ParseField FUNCTION_NAME_FIELD = new ParseField(NAME); private final Script script; diff --git a/core/src/main/java/org/elasticsearch/node/Node.java b/core/src/main/java/org/elasticsearch/node/Node.java index 8029bb40785..ac970d7d333 100644 --- a/core/src/main/java/org/elasticsearch/node/Node.java +++ b/core/src/main/java/org/elasticsearch/node/Node.java @@ -98,6 +98,7 @@ import org.elasticsearch.plugins.Plugin; import org.elasticsearch.plugins.PluginsService; import org.elasticsearch.plugins.RepositoryPlugin; import org.elasticsearch.plugins.ScriptPlugin; +import org.elasticsearch.plugins.SearchPlugin; import org.elasticsearch.repositories.RepositoriesModule; import org.elasticsearch.rest.RestController; import org.elasticsearch.script.ScriptModule; @@ -289,7 +290,7 @@ public class Node implements Closeable { ClusterModule clusterModule = new ClusterModule(settings, clusterService); modules.add(clusterModule); modules.add(new IndicesModule(namedWriteableRegistry, pluginsService.filterPlugins(MapperPlugin.class))); - modules.add(new SearchModule(settings, namedWriteableRegistry, false)); + modules.add(new SearchModule(settings, namedWriteableRegistry, false, pluginsService.filterPlugins(SearchPlugin.class))); modules.add(new ActionModule(DiscoveryNode.isIngestNode(settings), false, settings, clusterModule.getIndexNameExpressionResolver(), settingsModule.getClusterSettings(), pluginsService.filterPlugins(ActionPlugin.class))); diff --git a/core/src/main/java/org/elasticsearch/plugins/Plugin.java b/core/src/main/java/org/elasticsearch/plugins/Plugin.java index 9b1eaf8df0b..3c9cf675a63 100644 --- a/core/src/main/java/org/elasticsearch/plugins/Plugin.java +++ b/core/src/main/java/org/elasticsearch/plugins/Plugin.java @@ -38,8 +38,14 @@ import java.util.List; /** * An extension point allowing to plug in custom functionality. *

- * A plugin can be register custom extensions to builtin behavior by implementing onModule(AnyModule), - * and registering the extension with the given module. + * Implement any of these interfaces to extend Elasticsearch: + *

*/ public abstract class Plugin { diff --git a/core/src/main/java/org/elasticsearch/plugins/SearchPlugin.java b/core/src/main/java/org/elasticsearch/plugins/SearchPlugin.java new file mode 100644 index 00000000000..d02f4bf30f0 --- /dev/null +++ b/core/src/main/java/org/elasticsearch/plugins/SearchPlugin.java @@ -0,0 +1,177 @@ +/* + * 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.plugins; + +import org.elasticsearch.common.ParseField; +import org.elasticsearch.common.io.stream.NamedWriteable; +import org.elasticsearch.common.io.stream.Writeable; +import org.elasticsearch.common.io.stream.Writeable.Reader; +import org.elasticsearch.common.lucene.search.function.ScoreFunction; +import org.elasticsearch.common.xcontent.XContent; +import org.elasticsearch.index.query.functionscore.ScoreFunctionBuilder; +import org.elasticsearch.index.query.functionscore.ScoreFunctionParser; +import org.elasticsearch.search.aggregations.bucket.significant.SignificantTerms; +import org.elasticsearch.search.aggregations.bucket.significant.heuristics.SignificanceHeuristic; +import org.elasticsearch.search.aggregations.bucket.significant.heuristics.SignificanceHeuristicParser; +import org.elasticsearch.search.aggregations.pipeline.movavg.MovAvgPipelineAggregator; +import org.elasticsearch.search.aggregations.pipeline.movavg.models.MovAvgModel; +import org.elasticsearch.search.fetch.FetchSubPhase; +import org.elasticsearch.search.highlight.Highlighter; +import org.elasticsearch.search.suggest.Suggester; + +import java.util.List; +import java.util.Map; + +import static java.util.Collections.emptyList; +import static java.util.Collections.emptyMap; + +/** + * Plugin for extending search time behavior. + */ +public interface SearchPlugin { + /** + * The new {@link ScoreFunction}s defined by this plugin. + */ + default List> getScoreFunctions() { + return emptyList(); + } + /** + * The new {@link SignificanceHeuristic}s defined by this plugin. {@linkplain SignificanceHeuristic}s are used by the + * {@link SignificantTerms} aggregation to pick which terms are significant for a given query. + */ + default List> getSignificanceHeuristics() { + return emptyList(); + } + /** + * The new {@link MovAvgModel}s defined by this plugin. {@linkplain MovAvgModel}s are used by the {@link MovAvgPipelineAggregator} to + * model trends in data. + */ + default List> getMovingAverageModels() { + return emptyList(); + } + /** + * The new {@link FetchSubPhase}s defined by this plugin. + */ + default List getFetchSubPhases(FetchPhaseConstructionContext context) { + return emptyList(); + } + /** + * Get the {@link Highlighter}s defined by this plugin. + */ + default Map getHighlighters() { + return emptyMap(); + } + /** + * The new {@link Suggester}s defined by this plugin. + */ + default Map> getSuggesters() { + return emptyMap(); + } + + /** + * Specification of custom {@link ScoreFunction}. + */ + public class ScoreFunctionSpec> extends SearchPluginSpec> { + public ScoreFunctionSpec(ParseField name, Reader reader, ScoreFunctionParser parser) { + super(name, reader, parser); + } + + public ScoreFunctionSpec(String name, Reader reader, ScoreFunctionParser parser) { + super(name, reader, parser); + } + } + + /** + * Specification of search time behavior extension like a custom {@link MovAvgModel} or {@link ScoreFunction}. + * + * @param W the type of the main {@link NamedWriteable} for this spec. All specs have this but it isn't always *for* the same thing + * though, usually it is some sort of builder sent from the coordinating node to the data nodes executing the behavior + * @param P the type of the parser for this spec. The parser runs on the coordinating node, converting {@link XContent} into the + * behavior to execute + */ + public class SearchPluginSpec { + private final ParseField name; + private final Writeable.Reader reader; + private final P parser; + + /** + * Build the spec with a {@linkplain ParseField}. + * + * @param name the name of the behavior as a {@linkplain ParseField}. The parser is registered under all names specified by the + * {@linkplain ParseField} but the reader is only registered under the {@link ParseField#getPreferredName()} so be sure that + * that is the name that W's {@link NamedWriteable#getWriteableName()} returns. + * @param reader reader that reads the behavior from the internode protocol + * @param parser parser that read the behavior from a REST request + */ + public SearchPluginSpec(ParseField name, Writeable.Reader reader, P parser) { + this.name = name; + this.reader = reader; + this.parser = parser; + } + + /** + * Build the spec with a String. + * + * @param name the name of the behavior. The parser and the reader are are registered under this name so be sure that that is the + * name that W's {@link NamedWriteable#getWriteableName()} returns. + * @param reader reader that reads the behavior from the internode protocol + * @param parser parser that read the behavior from a REST request + */ + public SearchPluginSpec(String name, Writeable.Reader reader, P parser) { + this(new ParseField(name), reader, parser); + } + + /** + * The name of the thing being specified as a {@link ParseField}. This allows it to have deprecated names. + */ + public ParseField getName() { + return name; + } + + /** + * The reader responsible for reading the behavior from the internode protocol. + */ + public Writeable.Reader getReader() { + return reader; + } + + /** + * The parser responsible for converting {@link XContent} into the behavior. + */ + public P getParser() { + return parser; + } + } + + /** + * Context available during fetch phase construction. + */ + public class FetchPhaseConstructionContext { + private final Map highlighters; + + public FetchPhaseConstructionContext(Map highlighters) { + this.highlighters = highlighters; + } + + public Map getHighlighters() { + return highlighters; + } + } +} diff --git a/core/src/main/java/org/elasticsearch/search/Highlighters.java b/core/src/main/java/org/elasticsearch/search/Highlighters.java deleted file mode 100644 index b66a6bda640..00000000000 --- a/core/src/main/java/org/elasticsearch/search/Highlighters.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * 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.settings.Settings; -import org.elasticsearch.search.highlight.FastVectorHighlighter; -import org.elasticsearch.search.highlight.Highlighter; -import org.elasticsearch.search.highlight.PlainHighlighter; -import org.elasticsearch.search.highlight.PostingsHighlighter; - -import java.util.HashMap; -import java.util.Map; - -/** - * An extensions point and registry for all the highlighters a node supports. - */ -public final class Highlighters { - - private final Map parsers = new HashMap<>(); - - public Highlighters(Settings settings) { - registerHighlighter("fvh", new FastVectorHighlighter(settings)); - registerHighlighter("plain", new PlainHighlighter()); - registerHighlighter("postings", new PostingsHighlighter()); - } - - /** - * Returns the highlighter for the given key or null if there is no highlighter registered for that key. - */ - public Highlighter get(String key) { - return parsers.get(key); - } - - /** - * Registers a highlighter for the given key - * @param key the key the highlighter should be referenced by in the search request - * @param highlighter the highlighter instance - */ - void registerHighlighter(String key, Highlighter highlighter) { - if (highlighter == null) { - throw new IllegalArgumentException("Can't register null highlighter for key: [" + key + "]"); - } - if (parsers.putIfAbsent(key, highlighter) != null) { - throw new IllegalArgumentException("Can't register the same [highlighter] more than once for [" + key + "]"); - } - } -} diff --git a/core/src/main/java/org/elasticsearch/search/SearchModule.java b/core/src/main/java/org/elasticsearch/search/SearchModule.java index a0b15d91366..3d8e7109334 100644 --- a/core/src/main/java/org/elasticsearch/search/SearchModule.java +++ b/core/src/main/java/org/elasticsearch/search/SearchModule.java @@ -20,6 +20,7 @@ package org.elasticsearch.search; import org.apache.lucene.search.BooleanQuery; +import org.elasticsearch.common.NamedRegistry; import org.elasticsearch.common.ParseField; import org.elasticsearch.common.geo.ShapesAvailability; import org.elasticsearch.common.geo.builders.ShapeBuilders; @@ -91,6 +92,10 @@ import org.elasticsearch.index.query.functionscore.ScoreFunctionParser; import org.elasticsearch.index.query.functionscore.ScriptScoreFunctionBuilder; import org.elasticsearch.index.query.functionscore.WeightBuilder; import org.elasticsearch.indices.query.IndicesQueriesRegistry; +import org.elasticsearch.plugins.SearchPlugin; +import org.elasticsearch.plugins.SearchPlugin.FetchPhaseConstructionContext; +import org.elasticsearch.plugins.SearchPlugin.ScoreFunctionSpec; +import org.elasticsearch.plugins.SearchPlugin.SearchPluginSpec; import org.elasticsearch.search.action.SearchTransportService; import org.elasticsearch.search.aggregations.AggregationBuilder; import org.elasticsearch.search.aggregations.Aggregator; @@ -248,8 +253,11 @@ import org.elasticsearch.search.fetch.parent.ParentFieldSubFetchPhase; import org.elasticsearch.search.fetch.script.ScriptFieldsFetchSubPhase; import org.elasticsearch.search.fetch.source.FetchSourceSubPhase; import org.elasticsearch.search.fetch.version.VersionFetchSubPhase; +import org.elasticsearch.search.highlight.FastVectorHighlighter; import org.elasticsearch.search.highlight.HighlightPhase; import org.elasticsearch.search.highlight.Highlighter; +import org.elasticsearch.search.highlight.PlainHighlighter; +import org.elasticsearch.search.highlight.PostingsHighlighter; import org.elasticsearch.search.rescore.QueryRescorerBuilder; import org.elasticsearch.search.rescore.RescoreBuilder; import org.elasticsearch.search.sort.FieldSortBuilder; @@ -259,21 +267,33 @@ import org.elasticsearch.search.sort.ScriptSortBuilder; import org.elasticsearch.search.sort.SortBuilder; import org.elasticsearch.search.suggest.Suggester; import org.elasticsearch.search.suggest.Suggesters; +import org.elasticsearch.search.suggest.SuggestionBuilder; +import org.elasticsearch.search.suggest.completion.CompletionSuggester; +import org.elasticsearch.search.suggest.phrase.Laplace; +import org.elasticsearch.search.suggest.phrase.LinearInterpolation; +import org.elasticsearch.search.suggest.phrase.PhraseSuggester; +import org.elasticsearch.search.suggest.phrase.SmoothingModel; +import org.elasticsearch.search.suggest.phrase.StupidBackoff; +import org.elasticsearch.search.suggest.term.TermSuggester; -import java.util.HashSet; +import java.util.ArrayList; +import java.util.List; import java.util.Map; -import java.util.Objects; -import java.util.Set; import java.util.TreeMap; +import java.util.function.Consumer; +import java.util.function.Function; + +import static java.util.Collections.unmodifiableMap; +import static java.util.Objects.requireNonNull; /** - * + * Sets up things that can be done at search time like queries, aggregations, and suggesters. */ public class SearchModule extends AbstractModule { private final boolean transportClient; - private final Highlighters highlighters; - private final Suggesters suggesters; + private final Map highlighters; + private final Map> suggesters; private final ParseFieldRegistry> scoreFunctionParserRegistry = new ParseFieldRegistry<>("score_function"); private final IndicesQueriesRegistry queryParserRegistry = new IndicesQueriesRegistry(); private final ParseFieldRegistry aggregationParserRegistry = new ParseFieldRegistry<>("aggregation"); @@ -285,7 +305,7 @@ public class SearchModule extends AbstractModule { private final ParseFieldRegistry movingAverageModelParserRegistry = new ParseFieldRegistry<>( "moving_avg_model"); - private final Set fetchSubPhases = new HashSet<>(); + private final List fetchSubPhases = new ArrayList<>(); private final Settings settings; private final NamedWriteableRegistry namedWriteableRegistry; @@ -295,53 +315,22 @@ public class SearchModule extends AbstractModule { // pkg private so tests can mock Class searchServiceImpl = SearchService.class; - public SearchModule(Settings settings, NamedWriteableRegistry namedWriteableRegistry, boolean transportClient) { + public SearchModule(Settings settings, NamedWriteableRegistry namedWriteableRegistry, boolean transportClient, + List plugins) { this.settings = settings; this.namedWriteableRegistry = namedWriteableRegistry; this.transportClient = transportClient; - suggesters = new Suggesters(namedWriteableRegistry); - highlighters = new Highlighters(settings); - registerBuiltinScoreFunctionParsers(); + suggesters = setupSuggesters(plugins); + highlighters = setupHighlighters(settings, plugins); + registerScoreFunctions(plugins); registerBuiltinQueryParsers(); - registerBuiltinRescorers(); - registerBuiltinSorts(); - registerBuiltinValueFormats(); - registerBuiltinSignificanceHeuristics(); - registerBuiltinMovingAverageModels(); - registerBuiltinSubFetchPhases(); + registerRescorers(); + registerSorts(); + registerValueFormats(); + registerSignificanceHeuristics(plugins); + registerMovingAverageModels(plugins); registerBuiltinAggregations(); - } - - public void registerHighlighter(String key, Highlighter highligher) { - highlighters.registerHighlighter(key, highligher); - } - - public void registerSuggester(String key, Suggester suggester) { - suggesters.register(key, suggester); - } - - /** - * Register a new ScoreFunctionBuilder. Registration does two things: - *
    - *
  • Register the {@link ScoreFunctionParser} which parses XContent into a {@link ScoreFunctionBuilder} using its {@link ParseField} - *
  • - *
  • Register the {@link Writeable.Reader} which reads a stream representation of the builder under the - * {@linkplain ParseField#getPreferredName()}.
  • - *
- */ - public > void registerScoreFunction(Writeable.Reader reader, ScoreFunctionParser parser, - ParseField functionName) { - scoreFunctionParserRegistry.register(parser, functionName); - namedWriteableRegistry.register(ScoreFunctionBuilder.class, functionName.getPreferredName(), reader); - } - - /** - * Register a new ValueFormat. - */ - // private for now, we can consider making it public if there are actual use cases for plugins - // to register custom value formats - private void registerValueFormat(String name, Writeable.Reader reader) { - namedWriteableRegistry.register(DocValueFormat.class, name, reader); + registerFetchSubPhases(plugins); } /** @@ -360,39 +349,21 @@ public class SearchModule extends AbstractModule { namedWriteableRegistry.register(QueryBuilder.class, queryName.getPreferredName(), reader); } + public Suggesters getSuggesters() { + return new Suggesters(suggesters); + } + public IndicesQueriesRegistry getQueryParserRegistry() { return queryParserRegistry; } - /** - * Registers a {@link FetchSubPhase} instance. This sub phase is executed when docuemnts are fetched for instanced to highlight - * documents. - */ - public void registerFetchSubPhase(FetchSubPhase subPhase) { - fetchSubPhases.add(Objects.requireNonNull(subPhase, "FetchSubPhase must not be null")); - } - /** * Returns the {@link Highlighter} registry */ - public Highlighters getHighlighters() { + public Map getHighlighters() { return highlighters; } - /** - * Register a {@link SignificanceHeuristic}. - * - * @param heuristicName the name(s) at which the heuristic is parsed and streamed. The {@link ParseField#getPreferredName()} is the name - * under which it is streamed. All names work for the parser. - * @param reader reads the heuristic from a stream - * @param parser reads the heuristic from an XContentParser - */ - public void registerSignificanceHeuristic(ParseField heuristicName, Writeable.Reader reader, - SignificanceHeuristicParser parser) { - significanceHeuristicParserRegistry.register(parser, heuristicName); - namedWriteableRegistry.register(SignificanceHeuristic.class, heuristicName.getPreferredName(), reader); - } - /** * The registry of {@link SignificanceHeuristic}s. */ @@ -400,20 +371,6 @@ public class SearchModule extends AbstractModule { return significanceHeuristicParserRegistry; } - /** - * Register a {@link MovAvgModel}. - * - * @param modelName the name(s) at which the model is parsed and streamed. The {@link ParseField#getPreferredName()} is the name under - * which it is streamed. All named work for the parser. - * @param reader reads the model from a stream - * @param parser reads the model from an XContentParser - */ - public void registerMovingAverageModel(ParseField modelName, Writeable.Reader reader, - MovAvgModel.AbstractModelParser parser) { - movingAverageModelParserRegistry.register(parser, modelName); - namedWriteableRegistry.register(MovAvgModel.class, modelName.getPreferredName(), reader); - } - /** * The registry of {@link MovAvgModel}s. */ @@ -517,7 +474,7 @@ public class SearchModule extends AbstractModule { * NamedWriteableRegistry. */ bind(IndicesQueriesRegistry.class).toInstance(queryParserRegistry); - bind(Suggesters.class).toInstance(suggesters); + bind(Suggesters.class).toInstance(getSuggesters()); configureSearch(); configureShapes(); bind(AggregatorParsers.class).toInstance(aggregatorParsers); @@ -647,37 +604,88 @@ public class SearchModule extends AbstractModule { } } - private void registerBuiltinRescorers() { + private void registerRescorers() { namedWriteableRegistry.register(RescoreBuilder.class, QueryRescorerBuilder.NAME, QueryRescorerBuilder::new); } - private void registerBuiltinSorts() { + private void registerSorts() { namedWriteableRegistry.register(SortBuilder.class, GeoDistanceSortBuilder.NAME, GeoDistanceSortBuilder::new); namedWriteableRegistry.register(SortBuilder.class, ScoreSortBuilder.NAME, ScoreSortBuilder::new); namedWriteableRegistry.register(SortBuilder.class, ScriptSortBuilder.NAME, ScriptSortBuilder::new); namedWriteableRegistry.register(SortBuilder.class, FieldSortBuilder.NAME, FieldSortBuilder::new); } - private void registerBuiltinScoreFunctionParsers() { - registerScoreFunction(ScriptScoreFunctionBuilder::new, ScriptScoreFunctionBuilder::fromXContent, - ScriptScoreFunctionBuilder.FUNCTION_NAME_FIELD); - registerScoreFunction(GaussDecayFunctionBuilder::new, GaussDecayFunctionBuilder.PARSER, - GaussDecayFunctionBuilder.FUNCTION_NAME_FIELD); - registerScoreFunction(LinearDecayFunctionBuilder::new, LinearDecayFunctionBuilder.PARSER, - LinearDecayFunctionBuilder.FUNCTION_NAME_FIELD); - registerScoreFunction(ExponentialDecayFunctionBuilder::new, ExponentialDecayFunctionBuilder.PARSER, - ExponentialDecayFunctionBuilder.FUNCTION_NAME_FIELD); - registerScoreFunction(RandomScoreFunctionBuilder::new, RandomScoreFunctionBuilder::fromXContent, - RandomScoreFunctionBuilder.FUNCTION_NAME_FIELD); - registerScoreFunction(FieldValueFactorFunctionBuilder::new, FieldValueFactorFunctionBuilder::fromXContent, - FieldValueFactorFunctionBuilder.FUNCTION_NAME_FIELD); + private void registerFromPlugin(List plugins, Function> producer, Consumer consumer) { + for (SearchPlugin plugin : plugins) { + for (T t : producer.apply(plugin)) { + consumer.accept(t); + } + } + } + + public static void registerSmoothingModels(NamedWriteableRegistry namedWriteableRegistry) { + namedWriteableRegistry.register(SmoothingModel.class, Laplace.NAME, Laplace::new); + namedWriteableRegistry.register(SmoothingModel.class, LinearInterpolation.NAME, LinearInterpolation::new); + namedWriteableRegistry.register(SmoothingModel.class, StupidBackoff.NAME, StupidBackoff::new); + } + + private Map> setupSuggesters(List plugins) { + registerSmoothingModels(namedWriteableRegistry); + + // Suggester is weird - it is both a Parser and a reader.... + NamedRegistry> suggesters = new NamedRegistry>("suggester") { + @Override + public void register(String name, Suggester t) { + super.register(name, t); + namedWriteableRegistry.register(SuggestionBuilder.class, name, t); + } + }; + suggesters.register("phrase", PhraseSuggester.INSTANCE); + suggesters.register("term", TermSuggester.INSTANCE); + suggesters.register("completion", CompletionSuggester.INSTANCE); + + suggesters.extractAndRegister(plugins, SearchPlugin::getSuggesters); + return unmodifiableMap(suggesters.getRegistry()); + } + + private Map setupHighlighters(Settings settings, List plugins) { + NamedRegistry highlighters = new NamedRegistry<>("highlighter"); + highlighters.register("fvh", new FastVectorHighlighter(settings)); + highlighters.register("plain", new PlainHighlighter()); + highlighters.register("postings", new PostingsHighlighter()); + + highlighters.extractAndRegister(plugins, SearchPlugin::getHighlighters); + + return unmodifiableMap(highlighters.getRegistry()); + } + + private void registerScoreFunctions(List plugins) { + registerScoreFunction(new ScoreFunctionSpec<>(ScriptScoreFunctionBuilder.NAME, ScriptScoreFunctionBuilder::new, + ScriptScoreFunctionBuilder::fromXContent)); + registerScoreFunction( + new ScoreFunctionSpec<>(GaussDecayFunctionBuilder.NAME, GaussDecayFunctionBuilder::new, GaussDecayFunctionBuilder.PARSER)); + registerScoreFunction(new ScoreFunctionSpec<>(LinearDecayFunctionBuilder.NAME, LinearDecayFunctionBuilder::new, + LinearDecayFunctionBuilder.PARSER)); + registerScoreFunction(new ScoreFunctionSpec<>(ExponentialDecayFunctionBuilder.NAME, ExponentialDecayFunctionBuilder::new, + ExponentialDecayFunctionBuilder.PARSER)); + registerScoreFunction(new ScoreFunctionSpec<>(RandomScoreFunctionBuilder.NAME, RandomScoreFunctionBuilder::new, + RandomScoreFunctionBuilder::fromXContent)); + registerScoreFunction(new ScoreFunctionSpec<>(FieldValueFactorFunctionBuilder.NAME, FieldValueFactorFunctionBuilder::new, + FieldValueFactorFunctionBuilder::fromXContent)); //weight doesn't have its own parser, so every function supports it out of the box. //Can be a single function too when not associated to any other function, which is why it needs to be registered manually here. namedWriteableRegistry.register(ScoreFunctionBuilder.class, WeightBuilder.NAME, WeightBuilder::new); + + registerFromPlugin(plugins, SearchPlugin::getScoreFunctions, this::registerScoreFunction); } - private void registerBuiltinValueFormats() { + private void registerScoreFunction(ScoreFunctionSpec scoreFunction) { + scoreFunctionParserRegistry.register(scoreFunction.getParser(), scoreFunction.getName()); + namedWriteableRegistry.register(ScoreFunctionBuilder.class, scoreFunction.getName().getPreferredName(), scoreFunction.getReader()); + } + + private void registerValueFormats() { registerValueFormat(DocValueFormat.BOOLEAN.getWriteableName(), in -> DocValueFormat.BOOLEAN); registerValueFormat(DocValueFormat.DateTime.NAME, DocValueFormat.DateTime::new); registerValueFormat(DocValueFormat.Decimal.NAME, DocValueFormat.Decimal::new); @@ -686,24 +694,45 @@ public class SearchModule extends AbstractModule { registerValueFormat(DocValueFormat.RAW.getWriteableName(), in -> DocValueFormat.RAW); } - private void registerBuiltinSignificanceHeuristics() { - registerSignificanceHeuristic(ChiSquare.NAMES_FIELD, ChiSquare::new, ChiSquare.PARSER); - registerSignificanceHeuristic(GND.NAMES_FIELD, GND::new, GND.PARSER); - registerSignificanceHeuristic(JLHScore.NAMES_FIELD, JLHScore::new, JLHScore::parse); - registerSignificanceHeuristic(MutualInformation.NAMES_FIELD, MutualInformation::new, MutualInformation.PARSER); - registerSignificanceHeuristic(PercentageScore.NAMES_FIELD, PercentageScore::new, PercentageScore::parse); - registerSignificanceHeuristic(ScriptHeuristic.NAMES_FIELD, ScriptHeuristic::new, ScriptHeuristic::parse); + /** + * Register a new ValueFormat. + */ + private void registerValueFormat(String name, Writeable.Reader reader) { + namedWriteableRegistry.register(DocValueFormat.class, name, reader); } - private void registerBuiltinMovingAverageModels() { - registerMovingAverageModel(SimpleModel.NAME_FIELD, SimpleModel::new, SimpleModel.PARSER); - registerMovingAverageModel(LinearModel.NAME_FIELD, LinearModel::new, LinearModel.PARSER); - registerMovingAverageModel(EwmaModel.NAME_FIELD, EwmaModel::new, EwmaModel.PARSER); - registerMovingAverageModel(HoltLinearModel.NAME_FIELD, HoltLinearModel::new, HoltLinearModel.PARSER); - registerMovingAverageModel(HoltWintersModel.NAME_FIELD, HoltWintersModel::new, HoltWintersModel.PARSER); + private void registerSignificanceHeuristics(List plugins) { + registerSignificanceHeuristic(new SearchPluginSpec<>(ChiSquare.NAME, ChiSquare::new, ChiSquare.PARSER)); + registerSignificanceHeuristic(new SearchPluginSpec<>(GND.NAME, GND::new, GND.PARSER)); + registerSignificanceHeuristic(new SearchPluginSpec<>(JLHScore.NAME, JLHScore::new, JLHScore::parse)); + registerSignificanceHeuristic(new SearchPluginSpec<>(MutualInformation.NAME, MutualInformation::new, MutualInformation.PARSER)); + registerSignificanceHeuristic(new SearchPluginSpec<>(PercentageScore.NAME, PercentageScore::new, PercentageScore::parse)); + registerSignificanceHeuristic(new SearchPluginSpec<>(ScriptHeuristic.NAME, ScriptHeuristic::new, ScriptHeuristic::parse)); + + registerFromPlugin(plugins, SearchPlugin::getSignificanceHeuristics, this::registerSignificanceHeuristic); } - private void registerBuiltinSubFetchPhases() { + private void registerSignificanceHeuristic(SearchPluginSpec heuristic) { + significanceHeuristicParserRegistry.register(heuristic.getParser(), heuristic.getName()); + namedWriteableRegistry.register(SignificanceHeuristic.class, heuristic.getName().getPreferredName(), heuristic.getReader()); + } + + private void registerMovingAverageModels(List plugins) { + registerMovingAverageModel(new SearchPluginSpec<>(SimpleModel.NAME, SimpleModel::new, SimpleModel.PARSER)); + registerMovingAverageModel(new SearchPluginSpec<>(LinearModel.NAME, LinearModel::new, LinearModel.PARSER)); + registerMovingAverageModel(new SearchPluginSpec<>(EwmaModel.NAME, EwmaModel::new, EwmaModel.PARSER)); + registerMovingAverageModel(new SearchPluginSpec<>(HoltLinearModel.NAME, HoltLinearModel::new, HoltLinearModel.PARSER)); + registerMovingAverageModel(new SearchPluginSpec<>(HoltWintersModel.NAME, HoltWintersModel::new, HoltWintersModel.PARSER)); + + registerFromPlugin(plugins, SearchPlugin::getMovingAverageModels, this::registerMovingAverageModel); + } + + private void registerMovingAverageModel(SearchPluginSpec movAvgModel) { + movingAverageModelParserRegistry.register(movAvgModel.getParser(), movAvgModel.getName()); + namedWriteableRegistry.register(MovAvgModel.class, movAvgModel.getName().getPreferredName(), movAvgModel.getReader()); + } + + private void registerFetchSubPhases(List plugins) { registerFetchSubPhase(new ExplainFetchSubPhase()); registerFetchSubPhase(new FieldDataFieldsFetchSubPhase()); registerFetchSubPhase(new ScriptFieldsFetchSubPhase()); @@ -712,6 +741,17 @@ public class SearchModule extends AbstractModule { registerFetchSubPhase(new MatchedQueriesFetchSubPhase()); registerFetchSubPhase(new HighlightPhase(settings, highlighters)); registerFetchSubPhase(new ParentFieldSubFetchPhase()); + + FetchPhaseConstructionContext context = new FetchPhaseConstructionContext(highlighters); + registerFromPlugin(plugins, p -> p.getFetchSubPhases(context), this::registerFetchSubPhase); + } + + private void registerFetchSubPhase(FetchSubPhase subPhase) { + Class subPhaseClass = subPhase.getClass(); + if (fetchSubPhases.stream().anyMatch(p -> p.getClass().equals(subPhaseClass))) { + throw new IllegalArgumentException("FetchSubPhase [" + subPhaseClass + "] already registered"); + } + fetchSubPhases.add(requireNonNull(subPhase, "FetchSubPhase must not be null")); } private void registerBuiltinQueryParsers() { @@ -806,8 +846,4 @@ public class SearchModule extends AbstractModule { BucketSelectorPipelineAggregator.registerStreams(); SerialDiffPipelineAggregator.registerStreams(); } - - public Suggesters getSuggesters() { - return suggesters; - } } diff --git a/core/src/main/java/org/elasticsearch/search/aggregations/bucket/significant/heuristics/ChiSquare.java b/core/src/main/java/org/elasticsearch/search/aggregations/bucket/significant/heuristics/ChiSquare.java index d4af9c6be2f..de3c6c6acd0 100644 --- a/core/src/main/java/org/elasticsearch/search/aggregations/bucket/significant/heuristics/ChiSquare.java +++ b/core/src/main/java/org/elasticsearch/search/aggregations/bucket/significant/heuristics/ChiSquare.java @@ -21,14 +21,13 @@ package org.elasticsearch.search.aggregations.bucket.significant.heuristics; -import org.elasticsearch.common.ParseField; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.xcontent.XContentBuilder; import java.io.IOException; public class ChiSquare extends NXYSignificanceHeuristic { - public static final ParseField NAMES_FIELD = new ParseField("chi_square"); + public static final String NAME = "chi_square"; public ChiSquare(boolean includeNegatives, boolean backgroundIsSuperset) { super(includeNegatives, backgroundIsSuperset); @@ -51,7 +50,7 @@ public class ChiSquare extends NXYSignificanceHeuristic { @Override public int hashCode() { - int result = NAMES_FIELD.getPreferredName().hashCode(); + int result = NAME.hashCode(); result = 31 * result + super.hashCode(); return result; } @@ -74,12 +73,12 @@ public class ChiSquare extends NXYSignificanceHeuristic { @Override public String getWriteableName() { - return NAMES_FIELD.getPreferredName(); + return NAME; } @Override public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { - builder.startObject(NAMES_FIELD.getPreferredName()); + builder.startObject(NAME); super.build(builder); builder.endObject(); return builder; @@ -100,7 +99,7 @@ public class ChiSquare extends NXYSignificanceHeuristic { @Override public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { - builder.startObject(NAMES_FIELD.getPreferredName()); + builder.startObject(NAME); super.build(builder); builder.endObject(); return builder; diff --git a/core/src/main/java/org/elasticsearch/search/aggregations/bucket/significant/heuristics/GND.java b/core/src/main/java/org/elasticsearch/search/aggregations/bucket/significant/heuristics/GND.java index e97d98cee62..d8610dc05c8 100644 --- a/core/src/main/java/org/elasticsearch/search/aggregations/bucket/significant/heuristics/GND.java +++ b/core/src/main/java/org/elasticsearch/search/aggregations/bucket/significant/heuristics/GND.java @@ -22,7 +22,6 @@ package org.elasticsearch.search.aggregations.bucket.significant.heuristics; import org.elasticsearch.ElasticsearchParseException; -import org.elasticsearch.common.ParseField; import org.elasticsearch.common.ParseFieldMatcher; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; @@ -33,7 +32,7 @@ import org.elasticsearch.index.query.QueryShardException; import java.io.IOException; public class GND extends NXYSignificanceHeuristic { - public static final ParseField NAMES_FIELD = new ParseField("gnd"); + public static final String NAME = "gnd"; public GND(boolean backgroundIsSuperset) { super(true, backgroundIsSuperset); @@ -61,7 +60,7 @@ public class GND extends NXYSignificanceHeuristic { @Override public int hashCode() { - int result = NAMES_FIELD.getPreferredName().hashCode(); + int result = NAME.hashCode(); result = 31 * result + super.hashCode(); return result; } @@ -96,12 +95,12 @@ public class GND extends NXYSignificanceHeuristic { @Override public String getWriteableName() { - return NAMES_FIELD.getPreferredName(); + return NAME; } @Override public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { - builder.startObject(NAMES_FIELD.getPreferredName()); + builder.startObject(NAME); builder.field(BACKGROUND_IS_SUPERSET.getPreferredName(), backgroundIsSuperset); builder.endObject(); return builder; @@ -140,7 +139,7 @@ public class GND extends NXYSignificanceHeuristic { @Override public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { - builder.startObject(NAMES_FIELD.getPreferredName()); + builder.startObject(NAME); builder.field(BACKGROUND_IS_SUPERSET.getPreferredName(), backgroundIsSuperset); builder.endObject(); return builder; diff --git a/core/src/main/java/org/elasticsearch/search/aggregations/bucket/significant/heuristics/JLHScore.java b/core/src/main/java/org/elasticsearch/search/aggregations/bucket/significant/heuristics/JLHScore.java index e5099417c99..d426b146620 100644 --- a/core/src/main/java/org/elasticsearch/search/aggregations/bucket/significant/heuristics/JLHScore.java +++ b/core/src/main/java/org/elasticsearch/search/aggregations/bucket/significant/heuristics/JLHScore.java @@ -22,7 +22,6 @@ package org.elasticsearch.search.aggregations.bucket.significant.heuristics; import org.elasticsearch.ElasticsearchParseException; -import org.elasticsearch.common.ParseField; import org.elasticsearch.common.ParseFieldMatcher; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; @@ -33,7 +32,7 @@ import org.elasticsearch.index.query.QueryShardException; import java.io.IOException; public class JLHScore extends SignificanceHeuristic { - public static final ParseField NAMES_FIELD = new ParseField("jlh"); + public static final String NAME = "jlh"; public JLHScore() { } @@ -51,7 +50,7 @@ public class JLHScore extends SignificanceHeuristic { @Override public String getWriteableName() { - return NAMES_FIELD.getPreferredName(); + return NAME; } /** @@ -101,7 +100,7 @@ public class JLHScore extends SignificanceHeuristic { @Override public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { - builder.startObject(NAMES_FIELD.getPreferredName()).endObject(); + builder.startObject(NAME).endObject(); return builder; } @@ -133,7 +132,7 @@ public class JLHScore extends SignificanceHeuristic { @Override public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { - builder.startObject(NAMES_FIELD.getPreferredName()).endObject(); + builder.startObject(NAME).endObject(); return builder; } } diff --git a/core/src/main/java/org/elasticsearch/search/aggregations/bucket/significant/heuristics/MutualInformation.java b/core/src/main/java/org/elasticsearch/search/aggregations/bucket/significant/heuristics/MutualInformation.java index 7b76f0669d5..f8c8b61a729 100644 --- a/core/src/main/java/org/elasticsearch/search/aggregations/bucket/significant/heuristics/MutualInformation.java +++ b/core/src/main/java/org/elasticsearch/search/aggregations/bucket/significant/heuristics/MutualInformation.java @@ -21,14 +21,13 @@ package org.elasticsearch.search.aggregations.bucket.significant.heuristics; -import org.elasticsearch.common.ParseField; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.xcontent.XContentBuilder; import java.io.IOException; public class MutualInformation extends NXYSignificanceHeuristic { - public static final ParseField NAMES_FIELD = new ParseField("mutual_information"); + public static final String NAME = "mutual_information"; private static final double log2 = Math.log(2.0); @@ -54,7 +53,7 @@ public class MutualInformation extends NXYSignificanceHeuristic { @Override public int hashCode() { - int result = NAMES_FIELD.getPreferredName().hashCode(); + int result = NAME.hashCode(); result = 31 * result + super.hashCode(); return result; } @@ -108,18 +107,18 @@ public class MutualInformation extends NXYSignificanceHeuristic { @Override public String getWriteableName() { - return NAMES_FIELD.getPreferredName(); + return NAME; } @Override public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { - builder.startObject(NAMES_FIELD.getPreferredName()); + builder.startObject(NAME); super.build(builder); builder.endObject(); return builder; } - public static SignificanceHeuristicParser PARSER = new NXYParser() { + public static final SignificanceHeuristicParser PARSER = new NXYParser() { @Override protected SignificanceHeuristic newHeuristic(boolean includeNegatives, boolean backgroundIsSuperset) { return new MutualInformation(includeNegatives, backgroundIsSuperset); @@ -134,7 +133,7 @@ public class MutualInformation extends NXYSignificanceHeuristic { @Override public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { - builder.startObject(NAMES_FIELD.getPreferredName()); + builder.startObject(NAME); super.build(builder); builder.endObject(); return builder; diff --git a/core/src/main/java/org/elasticsearch/search/aggregations/bucket/significant/heuristics/PercentageScore.java b/core/src/main/java/org/elasticsearch/search/aggregations/bucket/significant/heuristics/PercentageScore.java index 19f7779432b..7bc117a0ec8 100644 --- a/core/src/main/java/org/elasticsearch/search/aggregations/bucket/significant/heuristics/PercentageScore.java +++ b/core/src/main/java/org/elasticsearch/search/aggregations/bucket/significant/heuristics/PercentageScore.java @@ -22,7 +22,6 @@ package org.elasticsearch.search.aggregations.bucket.significant.heuristics; import org.elasticsearch.ElasticsearchParseException; -import org.elasticsearch.common.ParseField; import org.elasticsearch.common.ParseFieldMatcher; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; @@ -33,7 +32,7 @@ import org.elasticsearch.index.query.QueryShardException; import java.io.IOException; public class PercentageScore extends SignificanceHeuristic { - public static final ParseField NAMES_FIELD = new ParseField("percentage"); + public static final String NAME = "percentage"; public PercentageScore() { } @@ -48,12 +47,12 @@ public class PercentageScore extends SignificanceHeuristic { @Override public String getWriteableName() { - return NAMES_FIELD.getPreferredName(); + return NAME; } @Override public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { - builder.startObject(NAMES_FIELD.getPreferredName()).endObject(); + builder.startObject(NAME).endObject(); return builder; } @@ -97,7 +96,7 @@ public class PercentageScore extends SignificanceHeuristic { @Override public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { - builder.startObject(NAMES_FIELD.getPreferredName()).endObject(); + builder.startObject(NAME).endObject(); return builder; } } diff --git a/core/src/main/java/org/elasticsearch/search/aggregations/bucket/significant/heuristics/ScriptHeuristic.java b/core/src/main/java/org/elasticsearch/search/aggregations/bucket/significant/heuristics/ScriptHeuristic.java index 19673bf6e9d..8a47a9bc44e 100644 --- a/core/src/main/java/org/elasticsearch/search/aggregations/bucket/significant/heuristics/ScriptHeuristic.java +++ b/core/src/main/java/org/elasticsearch/search/aggregations/bucket/significant/heuristics/ScriptHeuristic.java @@ -22,8 +22,6 @@ package org.elasticsearch.search.aggregations.bucket.significant.heuristics; import org.elasticsearch.ElasticsearchParseException; -import org.elasticsearch.cluster.ClusterState; -import org.elasticsearch.common.ParseField; import org.elasticsearch.common.ParseFieldMatcher; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; @@ -48,7 +46,7 @@ import java.util.Map; import java.util.Objects; public class ScriptHeuristic extends SignificanceHeuristic { - public static final ParseField NAMES_FIELD = new ParseField("script_heuristic"); + public static final String NAME = "script_heuristic"; private final LongAccessor subsetSizeHolder; private final LongAccessor supersetSizeHolder; @@ -123,12 +121,12 @@ public class ScriptHeuristic extends SignificanceHeuristic { @Override public String getWriteableName() { - return NAMES_FIELD.getPreferredName(); + return NAME; } @Override public XContentBuilder toXContent(XContentBuilder builder, Params builderParams) throws IOException { - builder.startObject(NAMES_FIELD.getPreferredName()); + builder.startObject(NAME); builder.field(ScriptField.SCRIPT.getPreferredName()); script.toXContent(builder, builderParams); builder.endObject(); @@ -205,7 +203,7 @@ public class ScriptHeuristic extends SignificanceHeuristic { @Override public XContentBuilder toXContent(XContentBuilder builder, Params builderParams) throws IOException { - builder.startObject(NAMES_FIELD.getPreferredName()); + builder.startObject(NAME); builder.field(ScriptField.SCRIPT.getPreferredName()); script.toXContent(builder, builderParams); builder.endObject(); diff --git a/core/src/main/java/org/elasticsearch/search/aggregations/bucket/significant/heuristics/SignificanceHeuristic.java b/core/src/main/java/org/elasticsearch/search/aggregations/bucket/significant/heuristics/SignificanceHeuristic.java index d2d085a2c0e..db9711c1a8d 100644 --- a/core/src/main/java/org/elasticsearch/search/aggregations/bucket/significant/heuristics/SignificanceHeuristic.java +++ b/core/src/main/java/org/elasticsearch/search/aggregations/bucket/significant/heuristics/SignificanceHeuristic.java @@ -19,12 +19,15 @@ package org.elasticsearch.search.aggregations.bucket.significant.heuristics; - import org.elasticsearch.common.io.stream.NamedWriteable; import org.elasticsearch.common.xcontent.ToXContent; import org.elasticsearch.search.aggregations.InternalAggregation; +import org.elasticsearch.search.aggregations.bucket.significant.SignificantTerms; import org.elasticsearch.search.internal.SearchContext; +/** + * Heuristic for that {@link SignificantTerms} uses to pick out significant terms. + */ public abstract class SignificanceHeuristic implements NamedWriteable, ToXContent { /** * @param subsetFreq The frequency of the term in the selected sample diff --git a/core/src/main/java/org/elasticsearch/search/aggregations/pipeline/movavg/models/EwmaModel.java b/core/src/main/java/org/elasticsearch/search/aggregations/pipeline/movavg/models/EwmaModel.java index 418930d2465..c7e6b0e8980 100644 --- a/core/src/main/java/org/elasticsearch/search/aggregations/pipeline/movavg/models/EwmaModel.java +++ b/core/src/main/java/org/elasticsearch/search/aggregations/pipeline/movavg/models/EwmaModel.java @@ -20,7 +20,6 @@ package org.elasticsearch.search.aggregations.pipeline.movavg.models; import org.elasticsearch.common.Nullable; -import org.elasticsearch.common.ParseField; import org.elasticsearch.common.ParseFieldMatcher; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; @@ -39,7 +38,6 @@ import java.util.Objects; */ public class EwmaModel extends MovAvgModel { public static final String NAME = "ewma"; - public static final ParseField NAME_FIELD = new ParseField(NAME); public static final double DEFAULT_ALPHA = 0.3; @@ -120,7 +118,7 @@ public class EwmaModel extends MovAvgModel { @Override public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { - builder.field(MovAvgPipelineAggregationBuilder.MODEL.getPreferredName(), NAME_FIELD.getPreferredName()); + builder.field(MovAvgPipelineAggregationBuilder.MODEL.getPreferredName(), NAME); builder.startObject(MovAvgPipelineAggregationBuilder.SETTINGS.getPreferredName()); builder.field("alpha", alpha); builder.endObject(); @@ -174,7 +172,7 @@ public class EwmaModel extends MovAvgModel { @Override public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { - builder.field(MovAvgPipelineAggregationBuilder.MODEL.getPreferredName(), NAME_FIELD.getPreferredName()); + builder.field(MovAvgPipelineAggregationBuilder.MODEL.getPreferredName(), NAME); builder.startObject(MovAvgPipelineAggregationBuilder.SETTINGS.getPreferredName()); builder.field("alpha", alpha); diff --git a/core/src/main/java/org/elasticsearch/search/aggregations/pipeline/movavg/models/HoltLinearModel.java b/core/src/main/java/org/elasticsearch/search/aggregations/pipeline/movavg/models/HoltLinearModel.java index 3ebfeb2ce26..d8a591972ec 100644 --- a/core/src/main/java/org/elasticsearch/search/aggregations/pipeline/movavg/models/HoltLinearModel.java +++ b/core/src/main/java/org/elasticsearch/search/aggregations/pipeline/movavg/models/HoltLinearModel.java @@ -20,7 +20,6 @@ package org.elasticsearch.search.aggregations.pipeline.movavg.models; import org.elasticsearch.common.Nullable; -import org.elasticsearch.common.ParseField; import org.elasticsearch.common.ParseFieldMatcher; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; @@ -38,7 +37,6 @@ import java.util.Objects; */ public class HoltLinearModel extends MovAvgModel { public static final String NAME = "holt"; - public static final ParseField NAME_FIELD = new ParseField(NAME); public static final double DEFAULT_ALPHA = 0.3; public static final double DEFAULT_BETA = 0.1; @@ -183,7 +181,7 @@ public class HoltLinearModel extends MovAvgModel { @Override public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { - builder.field(MovAvgPipelineAggregationBuilder.MODEL.getPreferredName(), NAME_FIELD.getPreferredName()); + builder.field(MovAvgPipelineAggregationBuilder.MODEL.getPreferredName(), NAME); builder.startObject(MovAvgPipelineAggregationBuilder.SETTINGS.getPreferredName()); builder.field("alpha", alpha); builder.field("beta", beta); @@ -255,7 +253,7 @@ public class HoltLinearModel extends MovAvgModel { @Override public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { - builder.field(MovAvgPipelineAggregationBuilder.MODEL.getPreferredName(), NAME_FIELD.getPreferredName()); + builder.field(MovAvgPipelineAggregationBuilder.MODEL.getPreferredName(), NAME); builder.startObject(MovAvgPipelineAggregationBuilder.SETTINGS.getPreferredName()); builder.field("alpha", alpha); builder.field("beta", beta); diff --git a/core/src/main/java/org/elasticsearch/search/aggregations/pipeline/movavg/models/HoltWintersModel.java b/core/src/main/java/org/elasticsearch/search/aggregations/pipeline/movavg/models/HoltWintersModel.java index 9249a4c7116..2130faf8674 100644 --- a/core/src/main/java/org/elasticsearch/search/aggregations/pipeline/movavg/models/HoltWintersModel.java +++ b/core/src/main/java/org/elasticsearch/search/aggregations/pipeline/movavg/models/HoltWintersModel.java @@ -44,7 +44,6 @@ import java.util.Objects; */ public class HoltWintersModel extends MovAvgModel { public static final String NAME = "holt_winters"; - public static final ParseField NAME_FIELD = new ParseField(NAME); public static final double DEFAULT_ALPHA = 0.3; public static final double DEFAULT_BETA = 0.1; @@ -366,7 +365,7 @@ public class HoltWintersModel extends MovAvgModel { @Override public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { - builder.field(MovAvgPipelineAggregationBuilder.MODEL.getPreferredName(), NAME_FIELD.getPreferredName()); + builder.field(MovAvgPipelineAggregationBuilder.MODEL.getPreferredName(), NAME); builder.startObject(MovAvgPipelineAggregationBuilder.SETTINGS.getPreferredName()); builder.field("alpha", alpha); builder.field("beta", beta); @@ -495,7 +494,7 @@ public class HoltWintersModel extends MovAvgModel { @Override public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { - builder.field(MovAvgPipelineAggregationBuilder.MODEL.getPreferredName(), NAME_FIELD.getPreferredName()); + builder.field(MovAvgPipelineAggregationBuilder.MODEL.getPreferredName(), NAME); builder.startObject(MovAvgPipelineAggregationBuilder.SETTINGS.getPreferredName()); builder.field("alpha", alpha); builder.field("beta", beta); diff --git a/core/src/main/java/org/elasticsearch/search/aggregations/pipeline/movavg/models/LinearModel.java b/core/src/main/java/org/elasticsearch/search/aggregations/pipeline/movavg/models/LinearModel.java index 01ca557ef32..089f3a430ca 100644 --- a/core/src/main/java/org/elasticsearch/search/aggregations/pipeline/movavg/models/LinearModel.java +++ b/core/src/main/java/org/elasticsearch/search/aggregations/pipeline/movavg/models/LinearModel.java @@ -21,7 +21,6 @@ package org.elasticsearch.search.aggregations.pipeline.movavg.models; import org.elasticsearch.common.Nullable; -import org.elasticsearch.common.ParseField; import org.elasticsearch.common.ParseFieldMatcher; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; @@ -40,7 +39,6 @@ import java.util.Map; */ public class LinearModel extends MovAvgModel { public static final String NAME = "linear"; - public static final ParseField NAME_FIELD = new ParseField("linear"); public LinearModel() { } @@ -102,7 +100,7 @@ public class LinearModel extends MovAvgModel { @Override public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { - builder.field(MovAvgPipelineAggregationBuilder.MODEL.getPreferredName(), NAME_FIELD.getPreferredName()); + builder.field(MovAvgPipelineAggregationBuilder.MODEL.getPreferredName(), NAME); return builder; } @@ -118,7 +116,7 @@ public class LinearModel extends MovAvgModel { public static class LinearModelBuilder implements MovAvgModelBuilder { @Override public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { - builder.field(MovAvgPipelineAggregationBuilder.MODEL.getPreferredName(), NAME_FIELD.getPreferredName()); + builder.field(MovAvgPipelineAggregationBuilder.MODEL.getPreferredName(), NAME); return builder; } diff --git a/core/src/main/java/org/elasticsearch/search/aggregations/pipeline/movavg/models/SimpleModel.java b/core/src/main/java/org/elasticsearch/search/aggregations/pipeline/movavg/models/SimpleModel.java index 7a6c72b00dc..14544881883 100644 --- a/core/src/main/java/org/elasticsearch/search/aggregations/pipeline/movavg/models/SimpleModel.java +++ b/core/src/main/java/org/elasticsearch/search/aggregations/pipeline/movavg/models/SimpleModel.java @@ -20,7 +20,6 @@ package org.elasticsearch.search.aggregations.pipeline.movavg.models; import org.elasticsearch.common.Nullable; -import org.elasticsearch.common.ParseField; import org.elasticsearch.common.ParseFieldMatcher; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; @@ -38,7 +37,6 @@ import java.util.Map; */ public class SimpleModel extends MovAvgModel { public static final String NAME = "simple"; - public static final ParseField NAME_FIELD = new ParseField(NAME); public SimpleModel() { } @@ -111,7 +109,7 @@ public class SimpleModel extends MovAvgModel { public static class SimpleModelBuilder implements MovAvgModelBuilder { @Override public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { - builder.field(MovAvgPipelineAggregationBuilder.MODEL.getPreferredName(), NAME_FIELD.getPreferredName()); + builder.field(MovAvgPipelineAggregationBuilder.MODEL.getPreferredName(), NAME); return builder; } diff --git a/core/src/main/java/org/elasticsearch/search/fetch/FetchPhase.java b/core/src/main/java/org/elasticsearch/search/fetch/FetchPhase.java index e884d32f3e4..beb64120788 100644 --- a/core/src/main/java/org/elasticsearch/search/fetch/FetchPhase.java +++ b/core/src/main/java/org/elasticsearch/search/fetch/FetchPhase.java @@ -72,7 +72,7 @@ public class FetchPhase implements SearchPhase { private final FetchSubPhase[] fetchSubPhases; - public FetchPhase(Set fetchSubPhases) { + public FetchPhase(List fetchSubPhases) { this.fetchSubPhases = fetchSubPhases.toArray(new FetchSubPhase[fetchSubPhases.size() + 1]); this.fetchSubPhases[fetchSubPhases.size()] = new InnerHitsFetchSubPhase(this); } diff --git a/core/src/main/java/org/elasticsearch/search/fetch/FetchSubPhase.java b/core/src/main/java/org/elasticsearch/search/fetch/FetchSubPhase.java index b55afe642ec..dec22308229 100644 --- a/core/src/main/java/org/elasticsearch/search/fetch/FetchSubPhase.java +++ b/core/src/main/java/org/elasticsearch/search/fetch/FetchSubPhase.java @@ -22,7 +22,6 @@ import org.apache.lucene.index.IndexReader; import org.apache.lucene.index.LeafReader; import org.apache.lucene.index.LeafReaderContext; import org.apache.lucene.search.IndexSearcher; -import org.elasticsearch.search.SearchHit; import org.elasticsearch.search.SearchParseElement; import org.elasticsearch.search.internal.InternalSearchHit; import org.elasticsearch.search.internal.SearchContext; @@ -32,7 +31,7 @@ import java.util.HashMap; import java.util.Map; /** - * + * Sub phase within the fetch phase used to fetch things *about* the documents highlghting. */ public interface FetchSubPhase { diff --git a/core/src/main/java/org/elasticsearch/search/highlight/HighlightPhase.java b/core/src/main/java/org/elasticsearch/search/highlight/HighlightPhase.java index 7952addbe8c..e3f1f2fd0bb 100644 --- a/core/src/main/java/org/elasticsearch/search/highlight/HighlightPhase.java +++ b/core/src/main/java/org/elasticsearch/search/highlight/HighlightPhase.java @@ -29,7 +29,6 @@ import org.elasticsearch.index.mapper.core.KeywordFieldMapper; import org.elasticsearch.index.mapper.core.StringFieldMapper; import org.elasticsearch.index.mapper.core.TextFieldMapper; import org.elasticsearch.index.mapper.internal.SourceFieldMapper; -import org.elasticsearch.search.Highlighters; import org.elasticsearch.search.fetch.FetchSubPhase; import org.elasticsearch.search.internal.SearchContext; @@ -43,9 +42,9 @@ import java.util.Map; public class HighlightPhase extends AbstractComponent implements FetchSubPhase { private static final List STANDARD_HIGHLIGHTERS_BY_PRECEDENCE = Arrays.asList("fvh", "postings", "plain"); - private final Highlighters highlighters; + private final Map highlighters; - public HighlightPhase(Settings settings, Highlighters highlighters) { + public HighlightPhase(Settings settings, Map highlighters) { super(settings); this.highlighters = highlighters; } diff --git a/core/src/main/java/org/elasticsearch/search/highlight/Highlighter.java b/core/src/main/java/org/elasticsearch/search/highlight/Highlighter.java index af4801f3633..f96536b2aff 100644 --- a/core/src/main/java/org/elasticsearch/search/highlight/Highlighter.java +++ b/core/src/main/java/org/elasticsearch/search/highlight/Highlighter.java @@ -21,7 +21,7 @@ package org.elasticsearch.search.highlight; import org.elasticsearch.index.mapper.FieldMapper; /** - * + * Highlights a search result. */ public interface Highlighter { diff --git a/core/src/main/java/org/elasticsearch/search/suggest/Suggesters.java b/core/src/main/java/org/elasticsearch/search/suggest/Suggesters.java index cea00eb4ad3..3f3f805d8f7 100644 --- a/core/src/main/java/org/elasticsearch/search/suggest/Suggesters.java +++ b/core/src/main/java/org/elasticsearch/search/suggest/Suggesters.java @@ -18,43 +18,16 @@ */ package org.elasticsearch.search.suggest; -import org.elasticsearch.common.io.stream.NamedWriteableRegistry; -import org.elasticsearch.search.suggest.completion.CompletionSuggester; -import org.elasticsearch.search.suggest.phrase.Laplace; -import org.elasticsearch.search.suggest.phrase.LinearInterpolation; -import org.elasticsearch.search.suggest.phrase.PhraseSuggester; -import org.elasticsearch.search.suggest.phrase.SmoothingModel; -import org.elasticsearch.search.suggest.phrase.StupidBackoff; -import org.elasticsearch.search.suggest.term.TermSuggester; - -import java.util.HashMap; import java.util.Map; /** - * + * Registry of Suggesters. This is only its own class to make Guice happy. */ public final class Suggesters { - private final Map> suggesters = new HashMap<>(); - private final NamedWriteableRegistry namedWriteableRegistry; + private final Map> suggesters; - public Suggesters(NamedWriteableRegistry namedWriteableRegistry) { - this.namedWriteableRegistry = namedWriteableRegistry; - register("phrase", PhraseSuggester.INSTANCE); - register("term", TermSuggester.INSTANCE); - register("completion", CompletionSuggester.INSTANCE); - - // Builtin smoothing models - namedWriteableRegistry.register(SmoothingModel.class, Laplace.NAME, Laplace::new); - namedWriteableRegistry.register(SmoothingModel.class, LinearInterpolation.NAME, LinearInterpolation::new); - namedWriteableRegistry.register(SmoothingModel.class, StupidBackoff.NAME, StupidBackoff::new); - } - - public void register(String key, Suggester suggester) { - if (suggesters.containsKey(key)) { - throw new IllegalArgumentException("Can't register the same [suggester] more than once for [" + key + "]"); - } - suggesters.put(key, suggester); - namedWriteableRegistry.register(SuggestionBuilder.class, key, suggester); + public Suggesters(Map> suggesters) { + this.suggesters = suggesters; } public Suggester getSuggester(String suggesterName) { diff --git a/core/src/test/java/org/elasticsearch/index/query/InnerHitBuilderTests.java b/core/src/test/java/org/elasticsearch/index/query/InnerHitBuilderTests.java index da8610f29f6..a48ace2e909 100644 --- a/core/src/test/java/org/elasticsearch/index/query/InnerHitBuilderTests.java +++ b/core/src/test/java/org/elasticsearch/index/query/InnerHitBuilderTests.java @@ -30,6 +30,8 @@ import java.util.List; import java.util.Map; import java.util.function.Supplier; +import static java.util.Collections.emptyList; + import org.apache.lucene.search.join.ScoreMode; import org.elasticsearch.common.ParseFieldMatcher; import org.elasticsearch.common.io.stream.BytesStreamOutput; @@ -67,7 +69,7 @@ public class InnerHitBuilderTests extends ESTestCase { @BeforeClass public static void init() { namedWriteableRegistry = new NamedWriteableRegistry(); - indicesQueriesRegistry = new SearchModule(Settings.EMPTY, namedWriteableRegistry, false).getQueryParserRegistry(); + indicesQueriesRegistry = new SearchModule(Settings.EMPTY, namedWriteableRegistry, false, emptyList()).getQueryParserRegistry(); } @AfterClass diff --git a/core/src/test/java/org/elasticsearch/index/query/functionscore/FunctionScoreQueryBuilderTests.java b/core/src/test/java/org/elasticsearch/index/query/functionscore/FunctionScoreQueryBuilderTests.java index e0bf9be2c92..6950a98631f 100644 --- a/core/src/test/java/org/elasticsearch/index/query/functionscore/FunctionScoreQueryBuilderTests.java +++ b/core/src/test/java/org/elasticsearch/index/query/functionscore/FunctionScoreQueryBuilderTests.java @@ -25,7 +25,6 @@ import org.apache.lucene.index.Term; import org.apache.lucene.search.MatchAllDocsQuery; import org.apache.lucene.search.Query; import org.apache.lucene.search.TermQuery; -import org.elasticsearch.common.ParseField; import org.elasticsearch.common.ParseFieldMatcher; import org.elasticsearch.common.ParsingException; import org.elasticsearch.common.geo.GeoPoint; @@ -37,11 +36,7 @@ import org.elasticsearch.common.lucene.search.function.FunctionScoreQuery; import org.elasticsearch.common.lucene.search.function.WeightFactorFunction; import org.elasticsearch.common.unit.DistanceUnit; import org.elasticsearch.common.xcontent.XContentType; -import org.elasticsearch.index.mapper.MapperService; import org.elasticsearch.index.query.AbstractQueryBuilder; -import org.elasticsearch.plugins.Plugin; -import org.elasticsearch.search.SearchModule; -import org.elasticsearch.test.AbstractQueryTestCase; import org.elasticsearch.index.query.MatchAllQueryBuilder; import org.elasticsearch.index.query.QueryBuilder; import org.elasticsearch.index.query.QueryParseContext; @@ -50,21 +45,24 @@ import org.elasticsearch.index.query.RandomQueryBuilder; import org.elasticsearch.index.query.TermQueryBuilder; import org.elasticsearch.index.query.WrapperQueryBuilder; import org.elasticsearch.index.query.functionscore.FunctionScoreQueryBuilder.FilterFunctionBuilder; +import org.elasticsearch.plugins.Plugin; +import org.elasticsearch.plugins.SearchPlugin; import org.elasticsearch.script.MockScriptEngine; import org.elasticsearch.script.Script; import org.elasticsearch.script.ScriptService; import org.elasticsearch.search.MultiValueMode; +import org.elasticsearch.test.AbstractQueryTestCase; import org.hamcrest.Matcher; import org.joda.time.DateTime; import org.joda.time.DateTimeZone; -import org.junit.Before; -import org.junit.BeforeClass; import java.io.IOException; import java.util.Collection; import java.util.Collections; +import java.util.List; import java.util.Map; +import static java.util.Collections.singletonList; import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder; import static org.elasticsearch.index.query.QueryBuilders.functionScoreQuery; import static org.elasticsearch.index.query.QueryBuilders.matchAllQuery; @@ -728,7 +726,6 @@ public class FunctionScoreQueryBuilderTests extends AbstractQueryTestCase> getScoreFunctions() { + return singletonList(new ScoreFunctionSpec<>(RandomScoreFunctionBuilderWithFixedSeed.NAME, + RandomScoreFunctionBuilderWithFixedSeed::new, RandomScoreFunctionBuilderWithFixedSeed::fromXContent)); } - } } diff --git a/core/src/test/java/org/elasticsearch/search/SearchModuleTests.java b/core/src/test/java/org/elasticsearch/search/SearchModuleTests.java index 20a557d56a6..14a167e52cf 100644 --- a/core/src/test/java/org/elasticsearch/search/SearchModuleTests.java +++ b/core/src/test/java/org/elasticsearch/search/SearchModuleTests.java @@ -27,75 +27,135 @@ import org.elasticsearch.common.xcontent.XContentHelper; import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.index.query.QueryParser; import org.elasticsearch.index.query.TermQueryBuilder; +import org.elasticsearch.index.query.functionscore.GaussDecayFunctionBuilder; import org.elasticsearch.indices.query.IndicesQueriesRegistry; +import org.elasticsearch.plugins.SearchPlugin; +import org.elasticsearch.search.aggregations.bucket.significant.heuristics.ChiSquare; +import org.elasticsearch.search.aggregations.bucket.significant.heuristics.SignificanceHeuristic; +import org.elasticsearch.search.aggregations.bucket.significant.heuristics.SignificanceHeuristicParser; +import org.elasticsearch.search.aggregations.pipeline.movavg.models.MovAvgModel; +import org.elasticsearch.search.aggregations.pipeline.movavg.models.SimpleModel; +import org.elasticsearch.search.fetch.FetchSubPhase; +import org.elasticsearch.search.fetch.explain.ExplainFetchSubPhase; import org.elasticsearch.search.highlight.CustomHighlighter; import org.elasticsearch.search.highlight.FastVectorHighlighter; +import org.elasticsearch.search.highlight.Highlighter; import org.elasticsearch.search.highlight.PlainHighlighter; import org.elasticsearch.search.highlight.PostingsHighlighter; import org.elasticsearch.search.suggest.CustomSuggester; +import org.elasticsearch.search.suggest.Suggester; +import org.elasticsearch.search.suggest.completion.CompletionSuggester; import org.elasticsearch.search.suggest.phrase.PhraseSuggester; +import org.elasticsearch.search.suggest.term.TermSuggester; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.Map; +import static java.util.Collections.emptyList; +import static java.util.Collections.singletonList; +import static java.util.Collections.singletonMap; import static org.hamcrest.Matchers.containsInAnyOrder; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.notNullValue; public class SearchModuleTests extends ModuleTestCase { - public void testDoubleRegister() { - SearchModule module = new SearchModule(Settings.EMPTY, new NamedWriteableRegistry(), false); - try { - module.registerHighlighter("fvh", new PlainHighlighter()); - } catch (IllegalArgumentException e) { - assertEquals(e.getMessage(), "Can't register the same [highlighter] more than once for [fvh]"); - } + public void testDoubleRegister() { + SearchPlugin registersDupeHighlighter = new SearchPlugin() { + @Override + public Map getHighlighters() { + return singletonMap("plain", new PlainHighlighter()); + } + }; + expectThrows(IllegalArgumentException.class, + () -> new SearchModule(Settings.EMPTY, new NamedWriteableRegistry(), false, singletonList(registersDupeHighlighter))); - try { - module.registerSuggester("term", PhraseSuggester.INSTANCE); - } catch (IllegalArgumentException e) { - assertEquals(e.getMessage(), "Can't register the same [suggester] more than once for [term]"); - } - } + SearchPlugin registersDupeSuggester = new SearchPlugin() { + @Override + public Map> getSuggesters() { + return singletonMap("term", TermSuggester.INSTANCE); + } + }; + expectThrows(IllegalArgumentException.class, + () -> new SearchModule(Settings.EMPTY, new NamedWriteableRegistry(), false, singletonList(registersDupeSuggester))); - public void testRegisterSuggester() { - SearchModule module = new SearchModule(Settings.EMPTY, new NamedWriteableRegistry(), false); - module.registerSuggester("custom", CustomSuggester.INSTANCE); - IllegalArgumentException e = expectThrows(IllegalArgumentException.class, - () -> module.registerSuggester("custom", CustomSuggester.INSTANCE)); - assertEquals("Can't register the same [suggester] more than once for [custom]", e.getMessage()); - } + SearchPlugin registersDupeScoreFunction = new SearchPlugin() { + @Override + public List> getScoreFunctions() { + return singletonList(new ScoreFunctionSpec<>(GaussDecayFunctionBuilder.NAME, GaussDecayFunctionBuilder::new, + GaussDecayFunctionBuilder.PARSER)); + } + }; + expectThrows(IllegalArgumentException.class, + () -> new SearchModule(Settings.EMPTY, new NamedWriteableRegistry(), false, singletonList(registersDupeScoreFunction))); - public void testRegisterHighlighter() { - SearchModule module = new SearchModule(Settings.EMPTY, new NamedWriteableRegistry(), false); - CustomHighlighter customHighlighter = new CustomHighlighter(); - module.registerHighlighter("custom", customHighlighter); - IllegalArgumentException exception = expectThrows(IllegalArgumentException.class, - () -> module.registerHighlighter("custom", new CustomHighlighter())); - assertEquals("Can't register the same [highlighter] more than once for [custom]", exception.getMessage()); + SearchPlugin registersDupeSignificanceHeuristic = new SearchPlugin() { + @Override + public List> getSignificanceHeuristics() { + return singletonList(new SearchPluginSpec<>(ChiSquare.NAME, ChiSquare::new, ChiSquare.PARSER)); + } + }; + expectThrows(IllegalArgumentException.class, () -> new SearchModule(Settings.EMPTY, new NamedWriteableRegistry(), false, + singletonList(registersDupeSignificanceHeuristic))); - exception = expectThrows(IllegalArgumentException.class, - () -> module.registerHighlighter("custom", null)); - assertEquals("Can't register null highlighter for key: [custom]", exception.getMessage()); - Highlighters highlighters = module.getHighlighters(); - assertEquals(highlighters.get("fvh").getClass(), FastVectorHighlighter.class); - assertEquals(highlighters.get("plain").getClass(), PlainHighlighter.class); - assertEquals(highlighters.get("postings").getClass(), PostingsHighlighter.class); - assertSame(highlighters.get("custom"), customHighlighter); - } + SearchPlugin registersDupeMovAvgModel = new SearchPlugin() { + @Override + public List> getMovingAverageModels() { + return singletonList(new SearchPluginSpec<>(SimpleModel.NAME, SimpleModel::new, SimpleModel.PARSER)); + } + }; + expectThrows(IllegalArgumentException.class, () -> new SearchModule(Settings.EMPTY, new NamedWriteableRegistry(), false, + singletonList(registersDupeMovAvgModel))); - public void testRegisterQueryParserDuplicate() { - SearchModule module = new SearchModule(Settings.EMPTY, new NamedWriteableRegistry(), false); + SearchPlugin registersDupeFetchSubPhase = new SearchPlugin() { + @Override + public List getFetchSubPhases(FetchPhaseConstructionContext context) { + return singletonList(new ExplainFetchSubPhase()); + } + }; + expectThrows(IllegalArgumentException.class, () -> new SearchModule(Settings.EMPTY, new NamedWriteableRegistry(), false, + singletonList(registersDupeFetchSubPhase))); + + SearchModule module = new SearchModule(Settings.EMPTY, new NamedWriteableRegistry(), false, emptyList()); IllegalArgumentException e = expectThrows(IllegalArgumentException.class, () -> module .registerQuery(TermQueryBuilder::new, TermQueryBuilder::fromXContent, TermQueryBuilder.QUERY_NAME_FIELD)); assertThat(e.getMessage(), containsString("] already registered for [query][term] while trying to register [org.elasticsearch.")); } + public void testRegisterSuggester() { + SearchModule module = new SearchModule(Settings.EMPTY, new NamedWriteableRegistry(), false, singletonList(new SearchPlugin() { + @Override + public Map> getSuggesters() { + return singletonMap("custom", CustomSuggester.INSTANCE); + } + })); + assertSame(TermSuggester.INSTANCE, module.getSuggesters().getSuggester("term")); + assertSame(PhraseSuggester.INSTANCE, module.getSuggesters().getSuggester("phrase")); + assertSame(CompletionSuggester.INSTANCE, module.getSuggesters().getSuggester("completion")); + assertSame(CustomSuggester.INSTANCE, module.getSuggesters().getSuggester("custom")); + } + + public void testRegisterHighlighter() { + CustomHighlighter customHighlighter = new CustomHighlighter(); + SearchModule module = new SearchModule(Settings.EMPTY, new NamedWriteableRegistry(), false, singletonList(new SearchPlugin() { + @Override + public Map getHighlighters() { + return singletonMap("custom", customHighlighter); + } + })); + + Map highlighters = module.getHighlighters(); + assertEquals(FastVectorHighlighter.class, highlighters.get("fvh").getClass()); + assertEquals(PlainHighlighter.class, highlighters.get("plain").getClass()); + assertEquals(PostingsHighlighter.class, highlighters.get("postings").getClass()); + assertSame(highlighters.get("custom"), customHighlighter); + } + public void testRegisteredQueries() throws IOException { - SearchModule module = new SearchModule(Settings.EMPTY, new NamedWriteableRegistry(), false); + SearchModule module = new SearchModule(Settings.EMPTY, new NamedWriteableRegistry(), false, emptyList()); List allSupportedQueries = new ArrayList<>(); Collections.addAll(allSupportedQueries, NON_DEPRECATED_QUERIES); Collections.addAll(allSupportedQueries, DEPRECATED_QUERIES); diff --git a/core/src/test/java/org/elasticsearch/search/aggregations/AggregatorParsingTests.java b/core/src/test/java/org/elasticsearch/search/aggregations/AggregatorParsingTests.java index 58b4b97db5c..2adaf408ed1 100644 --- a/core/src/test/java/org/elasticsearch/search/aggregations/AggregatorParsingTests.java +++ b/core/src/test/java/org/elasticsearch/search/aggregations/AggregatorParsingTests.java @@ -62,6 +62,7 @@ import java.util.Random; import java.util.regex.Matcher; import java.util.regex.Pattern; +import static java.util.Collections.emptyList; import static org.elasticsearch.test.ClusterServiceUtils.createClusterService; import static org.elasticsearch.test.ClusterServiceUtils.setState; import static org.hamcrest.Matchers.containsString; @@ -119,7 +120,7 @@ public class AggregatorParsingTests extends ESTestCase { protected void configure() { bindMapperExtension(); } - }, new SearchModule(settings, namedWriteableRegistry, false) { + }, new SearchModule(settings, namedWriteableRegistry, false, emptyList()) { @Override protected void configureSearch() { // Skip me diff --git a/core/src/test/java/org/elasticsearch/search/aggregations/BaseAggregationTestCase.java b/core/src/test/java/org/elasticsearch/search/aggregations/BaseAggregationTestCase.java index ddde1fd9eb6..9499603cf3a 100644 --- a/core/src/test/java/org/elasticsearch/search/aggregations/BaseAggregationTestCase.java +++ b/core/src/test/java/org/elasticsearch/search/aggregations/BaseAggregationTestCase.java @@ -63,6 +63,7 @@ import java.io.IOException; import java.util.Collections; import java.util.List; +import static java.util.Collections.emptyList; import static org.elasticsearch.test.ClusterServiceUtils.createClusterService; import static org.elasticsearch.test.ClusterServiceUtils.setState; import static org.hamcrest.Matchers.equalTo; @@ -151,7 +152,7 @@ public abstract class BaseAggregationTestCase> getSignificanceHeuristics() { + return singletonList(new SearchPluginSpec(SimpleHeuristic.NAME, + SimpleHeuristic::new, SimpleHeuristic::parse)); } @Override public List getNativeScripts() { - return Arrays.asList(new NativeSignificanceScoreScriptNoParams.Factory(), new NativeSignificanceScoreScriptWithParams.Factory()); + return Arrays.asList(new NativeSignificanceScoreScriptNoParams.Factory(), + new NativeSignificanceScoreScriptWithParams.Factory()); } } public static class SimpleHeuristic extends SignificanceHeuristic { - public static final ParseField NAMES_FIELD = new ParseField("simple"); + public static final String NAME = "simple"; public SimpleHeuristic() { } @@ -199,12 +201,12 @@ public class SignificantTermsSignificanceScoreIT extends ESIntegTestCase { @Override public String getWriteableName() { - return NAMES_FIELD.getPreferredName(); + return NAME; } @Override public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { - builder.startObject(NAMES_FIELD.getPreferredName()).endObject(); + builder.startObject(NAME).endObject(); return builder; } diff --git a/core/src/test/java/org/elasticsearch/search/aggregations/bucket/significant/SignificanceHeuristicTests.java b/core/src/test/java/org/elasticsearch/search/aggregations/bucket/significant/SignificanceHeuristicTests.java index 59aa7544d10..dd664ef70ca 100644 --- a/core/src/test/java/org/elasticsearch/search/aggregations/bucket/significant/SignificanceHeuristicTests.java +++ b/core/src/test/java/org/elasticsearch/search/aggregations/bucket/significant/SignificanceHeuristicTests.java @@ -62,6 +62,7 @@ import java.util.Collections; import java.util.HashMap; import java.util.List; +import static java.util.Collections.emptyList; import static org.elasticsearch.search.aggregations.AggregationBuilders.significantTerms; import static org.elasticsearch.test.VersionUtils.randomVersion; import static org.hamcrest.Matchers.equalTo; @@ -106,7 +107,7 @@ public class SignificanceHeuristicTests extends ESTestCase { ByteArrayInputStream inBuffer = new ByteArrayInputStream(outBuffer.toByteArray()); StreamInput in = new InputStreamStreamInput(inBuffer); NamedWriteableRegistry registry = new NamedWriteableRegistry(); - new SearchModule(Settings.EMPTY, registry, false); // populates the registry through side effects + new SearchModule(Settings.EMPTY, registry, false, emptyList()); // populates the registry through side effects in = new NamedWriteableAwareStreamInput(in, registry); in.setVersion(version); sigTerms[1].readFrom(in); @@ -202,7 +203,7 @@ public class SignificanceHeuristicTests extends ESTestCase { // 1. The output of the builders can actually be parsed // 2. The parser does not swallow parameters after a significance heuristic was defined public void testBuilderAndParser() throws Exception { - SearchModule searchModule = new SearchModule(Settings.EMPTY, new NamedWriteableRegistry(), false); + SearchModule searchModule = new SearchModule(Settings.EMPTY, new NamedWriteableRegistry(), false, emptyList()); ParseFieldRegistry heuristicParserMapper = searchModule.getSignificanceHeuristicParserRegistry(); SearchContext searchContext = new SignificantTermsTestSearchContext(); diff --git a/core/src/test/java/org/elasticsearch/search/builder/SearchSourceBuilderTests.java b/core/src/test/java/org/elasticsearch/search/builder/SearchSourceBuilderTests.java index 5a8b9fc767f..19a9b1c65f3 100644 --- a/core/src/test/java/org/elasticsearch/search/builder/SearchSourceBuilderTests.java +++ b/core/src/test/java/org/elasticsearch/search/builder/SearchSourceBuilderTests.java @@ -87,6 +87,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; +import static java.util.Collections.emptyList; import static org.elasticsearch.test.ClusterServiceUtils.createClusterService; import static org.elasticsearch.test.ClusterServiceUtils.setState; import static org.hamcrest.CoreMatchers.containsString; @@ -145,7 +146,7 @@ public class SearchSourceBuilderTests extends ESTestCase { bindMapperExtension(); } }, - new SearchModule(settings, namedWriteableRegistry, false) { + new SearchModule(settings, namedWriteableRegistry, false, emptyList()) { @Override protected void configureSearch() { // Skip me diff --git a/core/src/test/java/org/elasticsearch/search/fetch/FetchSubPhasePluginIT.java b/core/src/test/java/org/elasticsearch/search/fetch/FetchSubPhasePluginIT.java index b8e572b9dcc..f0ceec06f2c 100644 --- a/core/src/test/java/org/elasticsearch/search/fetch/FetchSubPhasePluginIT.java +++ b/core/src/test/java/org/elasticsearch/search/fetch/FetchSubPhasePluginIT.java @@ -32,11 +32,10 @@ import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.index.termvectors.TermVectorsService; import org.elasticsearch.plugins.Plugin; +import org.elasticsearch.plugins.SearchPlugin; import org.elasticsearch.search.SearchHitField; -import org.elasticsearch.search.SearchModule; import org.elasticsearch.search.SearchParseElement; import org.elasticsearch.search.builder.SearchSourceBuilder; -import org.elasticsearch.search.internal.InternalSearchHit; import org.elasticsearch.search.internal.InternalSearchHitField; import org.elasticsearch.search.internal.SearchContext; import org.elasticsearch.test.ESIntegTestCase; @@ -47,8 +46,10 @@ import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; +import java.util.List; import java.util.Map; +import static java.util.Collections.singletonList; import static java.util.Collections.singletonMap; import static org.elasticsearch.client.Requests.indexRequest; import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder; @@ -99,9 +100,10 @@ public class FetchSubPhasePluginIT extends ESIntegTestCase { equalTo(1)); } - public static class FetchTermVectorsPlugin extends Plugin { - public void onModule(SearchModule searchModule) { - searchModule.registerFetchSubPhase(new TermVectorsFetchSubPhase()); + public static class FetchTermVectorsPlugin extends Plugin implements SearchPlugin { + @Override + public List getFetchSubPhases(FetchPhaseConstructionContext context) { + return singletonList(new TermVectorsFetchSubPhase()); } } diff --git a/core/src/test/java/org/elasticsearch/search/functionscore/FunctionScorePluginIT.java b/core/src/test/java/org/elasticsearch/search/functionscore/FunctionScorePluginIT.java index e5be795d8f5..2c00fe2c740 100644 --- a/core/src/test/java/org/elasticsearch/search/functionscore/FunctionScorePluginIT.java +++ b/core/src/test/java/org/elasticsearch/search/functionscore/FunctionScorePluginIT.java @@ -23,7 +23,6 @@ import org.apache.lucene.search.Explanation; import org.elasticsearch.action.ActionFuture; import org.elasticsearch.action.search.SearchResponse; import org.elasticsearch.action.search.SearchType; -import org.elasticsearch.common.ParseField; import org.elasticsearch.common.Priority; import org.elasticsearch.common.bytes.BytesReference; import org.elasticsearch.common.io.stream.StreamInput; @@ -32,8 +31,8 @@ import org.elasticsearch.index.query.functionscore.DecayFunctionBuilder; import org.elasticsearch.index.query.functionscore.DecayFunctionParser; import org.elasticsearch.index.query.functionscore.ScoreFunctionParser; import org.elasticsearch.plugins.Plugin; +import org.elasticsearch.plugins.SearchPlugin; import org.elasticsearch.search.SearchHits; -import org.elasticsearch.search.SearchModule; import org.elasticsearch.test.ESIntegTestCase; import org.elasticsearch.test.ESIntegTestCase.ClusterScope; import org.elasticsearch.test.ESIntegTestCase.Scope; @@ -41,7 +40,9 @@ import org.elasticsearch.test.hamcrest.ElasticsearchAssertions; import java.io.IOException; import java.util.Collection; +import java.util.List; +import static java.util.Collections.singletonList; import static org.elasticsearch.client.Requests.indexRequest; import static org.elasticsearch.client.Requests.searchRequest; import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder; @@ -94,16 +95,16 @@ public class FunctionScorePluginIT extends ESIntegTestCase { } - public static class CustomDistanceScorePlugin extends Plugin { - public void onModule(SearchModule scoreModule) { - scoreModule.registerScoreFunction(CustomDistanceScoreBuilder::new, CustomDistanceScoreBuilder.PARSER, - CustomDistanceScoreBuilder.FUNCTION_NAME_FIELD); + public static class CustomDistanceScorePlugin extends Plugin implements SearchPlugin { + @Override + public List> getScoreFunctions() { + return singletonList(new ScoreFunctionSpec<>(CustomDistanceScoreBuilder.NAME, CustomDistanceScoreBuilder::new, + CustomDistanceScoreBuilder.PARSER)); } } public static class CustomDistanceScoreBuilder extends DecayFunctionBuilder { public static final String NAME = "linear_mult"; - public static final ParseField FUNCTION_NAME_FIELD = new ParseField(NAME); public static final ScoreFunctionParser PARSER = new DecayFunctionParser<>( CustomDistanceScoreBuilder::new); diff --git a/core/src/test/java/org/elasticsearch/search/highlight/CustomHighlighterPlugin.java b/core/src/test/java/org/elasticsearch/search/highlight/CustomHighlighterPlugin.java index f6d56b8b39c..0f42fd43f00 100644 --- a/core/src/test/java/org/elasticsearch/search/highlight/CustomHighlighterPlugin.java +++ b/core/src/test/java/org/elasticsearch/search/highlight/CustomHighlighterPlugin.java @@ -20,11 +20,15 @@ package org.elasticsearch.search.highlight; import org.elasticsearch.plugins.Plugin; -import org.elasticsearch.search.SearchModule; +import org.elasticsearch.plugins.SearchPlugin; -public class CustomHighlighterPlugin extends Plugin { +import java.util.Map; - public void onModule(SearchModule highlightModule) { - highlightModule.registerHighlighter("test-custom", new CustomHighlighter()); +import static java.util.Collections.singletonMap; + +public class CustomHighlighterPlugin extends Plugin implements SearchPlugin { + @Override + public Map getHighlighters() { + return singletonMap("test-custom", new CustomHighlighter()); } } diff --git a/core/src/test/java/org/elasticsearch/search/highlight/CustomHighlighterSearchIT.java b/core/src/test/java/org/elasticsearch/search/highlight/CustomHighlighterSearchIT.java index 4b5153b2417..2fea2ecfc2f 100644 --- a/core/src/test/java/org/elasticsearch/search/highlight/CustomHighlighterSearchIT.java +++ b/core/src/test/java/org/elasticsearch/search/highlight/CustomHighlighterSearchIT.java @@ -35,7 +35,7 @@ import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertHigh import static org.hamcrest.Matchers.equalTo; /** - * + * Integration test for highlighters registered by a plugin. */ @ClusterScope(scope = Scope.SUITE, supportsDedicatedMasters = false, numDataNodes = 1) public class CustomHighlighterSearchIT extends ESIntegTestCase { diff --git a/core/src/test/java/org/elasticsearch/search/highlight/HighlightBuilderTests.java b/core/src/test/java/org/elasticsearch/search/highlight/HighlightBuilderTests.java index 1e3c5453fd7..17a674d669a 100644 --- a/core/src/test/java/org/elasticsearch/search/highlight/HighlightBuilderTests.java +++ b/core/src/test/java/org/elasticsearch/search/highlight/HighlightBuilderTests.java @@ -68,6 +68,7 @@ import java.util.TreeSet; import java.util.function.BiConsumer; import java.util.function.Function; +import static java.util.Collections.emptyList; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.not; @@ -83,7 +84,7 @@ public class HighlightBuilderTests extends ESTestCase { @BeforeClass public static void init() { namedWriteableRegistry = new NamedWriteableRegistry(); - indicesQueriesRegistry = new SearchModule(Settings.EMPTY, namedWriteableRegistry, false).getQueryParserRegistry(); + indicesQueriesRegistry = new SearchModule(Settings.EMPTY, namedWriteableRegistry, false, emptyList()).getQueryParserRegistry(); } @AfterClass diff --git a/core/src/test/java/org/elasticsearch/search/rescore/QueryRescoreBuilderTests.java b/core/src/test/java/org/elasticsearch/search/rescore/QueryRescoreBuilderTests.java index 28eb56bdcaf..ed38fe8405a 100644 --- a/core/src/test/java/org/elasticsearch/search/rescore/QueryRescoreBuilderTests.java +++ b/core/src/test/java/org/elasticsearch/search/rescore/QueryRescoreBuilderTests.java @@ -55,6 +55,7 @@ import org.junit.BeforeClass; import java.io.IOException; +import static java.util.Collections.emptyList; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.not; @@ -70,7 +71,7 @@ public class QueryRescoreBuilderTests extends ESTestCase { @BeforeClass public static void init() { namedWriteableRegistry = new NamedWriteableRegistry(); - indicesQueriesRegistry = new SearchModule(Settings.EMPTY, namedWriteableRegistry, false).getQueryParserRegistry(); + indicesQueriesRegistry = new SearchModule(Settings.EMPTY, namedWriteableRegistry, false, emptyList()).getQueryParserRegistry(); } @AfterClass diff --git a/core/src/test/java/org/elasticsearch/search/sort/AbstractSortTestCase.java b/core/src/test/java/org/elasticsearch/search/sort/AbstractSortTestCase.java index 8d46372aa42..9673ed8ef00 100644 --- a/core/src/test/java/org/elasticsearch/search/sort/AbstractSortTestCase.java +++ b/core/src/test/java/org/elasticsearch/search/sort/AbstractSortTestCase.java @@ -75,6 +75,7 @@ import java.nio.file.Path; import java.util.Collections; import java.util.Map; +import static java.util.Collections.emptyList; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.not; @@ -106,7 +107,7 @@ public abstract class AbstractSortTestCase> extends EST }; namedWriteableRegistry = new NamedWriteableRegistry(); - indicesQueriesRegistry = new SearchModule(Settings.EMPTY, namedWriteableRegistry, false).getQueryParserRegistry(); + indicesQueriesRegistry = new SearchModule(Settings.EMPTY, namedWriteableRegistry, false, emptyList()).getQueryParserRegistry(); } @AfterClass diff --git a/core/src/test/java/org/elasticsearch/search/sort/SortBuilderTests.java b/core/src/test/java/org/elasticsearch/search/sort/SortBuilderTests.java index 54b12216302..511c2830495 100644 --- a/core/src/test/java/org/elasticsearch/search/sort/SortBuilderTests.java +++ b/core/src/test/java/org/elasticsearch/search/sort/SortBuilderTests.java @@ -41,6 +41,8 @@ import java.util.ArrayList; import java.util.Iterator; import java.util.List; +import static java.util.Collections.emptyList; + public class SortBuilderTests extends ESTestCase { private static final int NUMBER_OF_RUNS = 20; @@ -52,7 +54,7 @@ public class SortBuilderTests extends ESTestCase { @BeforeClass public static void init() { namedWriteableRegistry = new NamedWriteableRegistry(); - indicesQueriesRegistry = new SearchModule(Settings.EMPTY, namedWriteableRegistry, false).getQueryParserRegistry(); + indicesQueriesRegistry = new SearchModule(Settings.EMPTY, namedWriteableRegistry, false, emptyList()).getQueryParserRegistry(); } @AfterClass diff --git a/core/src/test/java/org/elasticsearch/search/suggest/AbstractSuggestionBuilderTestCase.java b/core/src/test/java/org/elasticsearch/search/suggest/AbstractSuggestionBuilderTestCase.java index b67036e1152..c240dbefeb1 100644 --- a/core/src/test/java/org/elasticsearch/search/suggest/AbstractSuggestionBuilderTestCase.java +++ b/core/src/test/java/org/elasticsearch/search/suggest/AbstractSuggestionBuilderTestCase.java @@ -39,6 +39,8 @@ import org.junit.AfterClass; import org.junit.BeforeClass; import java.io.IOException; + +import static java.util.Collections.emptyList; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.not; @@ -56,7 +58,7 @@ public abstract class AbstractSuggestionBuilderTestCase { - public static CustomSuggester INSTANCE = new CustomSuggester(); + public static final CustomSuggester INSTANCE = new CustomSuggester(); // This is a pretty dumb implementation which returns the original text + fieldName + custom config option + 12 or 123 @Override diff --git a/core/src/test/java/org/elasticsearch/search/suggest/CustomSuggesterPlugin.java b/core/src/test/java/org/elasticsearch/search/suggest/CustomSuggesterPlugin.java index dc78aec69cf..583ac365fad 100644 --- a/core/src/test/java/org/elasticsearch/search/suggest/CustomSuggesterPlugin.java +++ b/core/src/test/java/org/elasticsearch/search/suggest/CustomSuggesterPlugin.java @@ -19,12 +19,15 @@ package org.elasticsearch.search.suggest; import org.elasticsearch.plugins.Plugin; -import org.elasticsearch.search.SearchModule; +import org.elasticsearch.plugins.SearchPlugin; -public class CustomSuggesterPlugin extends Plugin { +import java.util.Map; - public void onModule(SearchModule searchModule) { - searchModule.registerSuggester("custom", CustomSuggester.INSTANCE); +import static java.util.Collections.singletonMap; + +public class CustomSuggesterPlugin extends Plugin implements SearchPlugin { + @Override + public Map> getSuggesters() { + return singletonMap("custom", CustomSuggester.INSTANCE); } - } diff --git a/core/src/test/java/org/elasticsearch/search/suggest/CustomSuggesterSearchIT.java b/core/src/test/java/org/elasticsearch/search/suggest/CustomSuggesterSearchIT.java index 28f8ec49a57..c792bc02c92 100644 --- a/core/src/test/java/org/elasticsearch/search/suggest/CustomSuggesterSearchIT.java +++ b/core/src/test/java/org/elasticsearch/search/suggest/CustomSuggesterSearchIT.java @@ -51,7 +51,7 @@ import static org.hamcrest.Matchers.hasSize; import static org.hamcrest.Matchers.is; /** - * + * Integration test for registering a custom suggester. */ @ClusterScope(scope= Scope.SUITE, numDataNodes =1) public class CustomSuggesterSearchIT extends ESIntegTestCase { diff --git a/core/src/test/java/org/elasticsearch/search/suggest/SuggestBuilderTests.java b/core/src/test/java/org/elasticsearch/search/suggest/SuggestBuilderTests.java index 77dc2e01b56..cb375db8c31 100644 --- a/core/src/test/java/org/elasticsearch/search/suggest/SuggestBuilderTests.java +++ b/core/src/test/java/org/elasticsearch/search/suggest/SuggestBuilderTests.java @@ -22,6 +22,7 @@ package org.elasticsearch.search.suggest; import org.elasticsearch.common.ParseFieldMatcher; import org.elasticsearch.common.io.stream.NamedWriteableRegistry; import org.elasticsearch.common.io.stream.StreamInput; +import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.xcontent.ToXContent; import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentFactory; @@ -30,6 +31,7 @@ import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.common.xcontent.XContentType; import org.elasticsearch.index.query.QueryParseContext; import org.elasticsearch.indices.query.IndicesQueriesRegistry; +import org.elasticsearch.search.SearchModule; import org.elasticsearch.search.suggest.completion.CompletionSuggesterBuilderTests; import org.elasticsearch.search.suggest.completion.WritableTestCase; import org.elasticsearch.search.suggest.phrase.PhraseSuggestionBuilderTests; @@ -40,6 +42,8 @@ import org.junit.BeforeClass; import java.io.IOException; import java.util.Map.Entry; +import static java.util.Collections.emptyList; + public class SuggestBuilderTests extends WritableTestCase { private static NamedWriteableRegistry namedWriteableRegistry; @@ -51,7 +55,7 @@ public class SuggestBuilderTests extends WritableTestCase { @BeforeClass public static void init() { namedWriteableRegistry = new NamedWriteableRegistry(); - suggesters = new Suggesters(namedWriteableRegistry); + suggesters = new SearchModule(Settings.EMPTY, namedWriteableRegistry, false, emptyList()).getSuggesters(); } @AfterClass diff --git a/core/src/test/java/org/elasticsearch/search/suggest/phrase/SmoothingModelTestCase.java b/core/src/test/java/org/elasticsearch/search/suggest/phrase/SmoothingModelTestCase.java index c7b883b583b..ff06a74756f 100644 --- a/core/src/test/java/org/elasticsearch/search/suggest/phrase/SmoothingModelTestCase.java +++ b/core/src/test/java/org/elasticsearch/search/suggest/phrase/SmoothingModelTestCase.java @@ -44,7 +44,7 @@ import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.common.xcontent.XContentType; import org.elasticsearch.index.query.QueryParseContext; import org.elasticsearch.indices.query.IndicesQueriesRegistry; -import org.elasticsearch.search.suggest.Suggesters; +import org.elasticsearch.search.SearchModule; import org.elasticsearch.test.ESTestCase; import org.junit.AfterClass; import org.junit.BeforeClass; @@ -67,7 +67,7 @@ public abstract class SmoothingModelTestCase extends ESTestCase { public static void init() { if (namedWriteableRegistry == null) { namedWriteableRegistry = new NamedWriteableRegistry(); - new Suggesters(namedWriteableRegistry); + SearchModule.registerSmoothingModels(namedWriteableRegistry); } } diff --git a/docs/reference/migration/migrate_5_0/plugins.asciidoc b/docs/reference/migration/migrate_5_0/plugins.asciidoc index 79583c6b925..41018278853 100644 --- a/docs/reference/migration/migrate_5_0/plugins.asciidoc +++ b/docs/reference/migration/migrate_5_0/plugins.asciidoc @@ -141,6 +141,12 @@ remove their `onModule(ActionModule)` implementation. Plugins that register custom `RestHandler`s should implement `ActionPlugin` and remove their `onModule(NetworkModule)` implemnetation. +==== SearchPlugin + +Plugins that register custom search time behavior (`Suggester`, `ScoreFunction`, +`FetchSubPhase`, `Highlighter`, etc) should implement `SearchPlugin` and remove +their `onModule(SearchModule)` implementation. + ==== Mapper-Size plugin The metadata field `_size` is not accessible in aggregations, scripts and when diff --git a/modules/lang-mustache/src/test/java/org/elasticsearch/messy/tests/TemplateQueryParserTests.java b/modules/lang-mustache/src/test/java/org/elasticsearch/messy/tests/TemplateQueryParserTests.java index fb8979562ff..84e615e75c4 100644 --- a/modules/lang-mustache/src/test/java/org/elasticsearch/messy/tests/TemplateQueryParserTests.java +++ b/modules/lang-mustache/src/test/java/org/elasticsearch/messy/tests/TemplateQueryParserTests.java @@ -118,7 +118,7 @@ public class TemplateQueryParserTests extends ESTestCase { b.bind(CircuitBreakerService.class).to(NoneCircuitBreakerService.class); }, settingsModule, - new SearchModule(settings, new NamedWriteableRegistry(), false) { + new SearchModule(settings, new NamedWriteableRegistry(), false, emptyList()) { @Override protected void configureSearch() { // skip so we don't need transport diff --git a/modules/percolator/src/main/java/org/elasticsearch/percolator/PercolatorHighlightSubFetchPhase.java b/modules/percolator/src/main/java/org/elasticsearch/percolator/PercolatorHighlightSubFetchPhase.java index b9f52a024e6..2e9fd517d53 100644 --- a/modules/percolator/src/main/java/org/elasticsearch/percolator/PercolatorHighlightSubFetchPhase.java +++ b/modules/percolator/src/main/java/org/elasticsearch/percolator/PercolatorHighlightSubFetchPhase.java @@ -33,9 +33,9 @@ import org.elasticsearch.common.lucene.search.function.FunctionScoreQuery; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.text.Text; import org.elasticsearch.index.query.ParsedQuery; -import org.elasticsearch.search.Highlighters; import org.elasticsearch.search.fetch.FetchSubPhase; import org.elasticsearch.search.highlight.HighlightPhase; +import org.elasticsearch.search.highlight.Highlighter; import org.elasticsearch.search.highlight.SearchContextHighlight; import org.elasticsearch.search.internal.InternalSearchHit; import org.elasticsearch.search.internal.SearchContext; @@ -44,6 +44,7 @@ import org.elasticsearch.search.internal.SubSearchContext; import java.io.IOException; import java.util.Collections; import java.util.List; +import java.util.Map; /** * Highlighting in the case of the percolate query is a bit different, because the PercolateQuery itself doesn't get highlighted, @@ -51,7 +52,7 @@ import java.util.List; */ public final class PercolatorHighlightSubFetchPhase extends HighlightPhase { - public PercolatorHighlightSubFetchPhase(Settings settings, Highlighters highlighters) { + public PercolatorHighlightSubFetchPhase(Settings settings, Map highlighters) { super(settings, highlighters); } diff --git a/modules/percolator/src/main/java/org/elasticsearch/percolator/PercolatorPlugin.java b/modules/percolator/src/main/java/org/elasticsearch/percolator/PercolatorPlugin.java index 4359568b3f6..f0bf5e77dba 100644 --- a/modules/percolator/src/main/java/org/elasticsearch/percolator/PercolatorPlugin.java +++ b/modules/percolator/src/main/java/org/elasticsearch/percolator/PercolatorPlugin.java @@ -27,15 +27,19 @@ import org.elasticsearch.index.mapper.Mapper; import org.elasticsearch.plugins.ActionPlugin; import org.elasticsearch.plugins.MapperPlugin; import org.elasticsearch.plugins.Plugin; +import org.elasticsearch.plugins.SearchPlugin; import org.elasticsearch.rest.RestHandler; import org.elasticsearch.search.SearchModule; +import org.elasticsearch.search.fetch.FetchSubPhase; import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Map; -public class PercolatorPlugin extends Plugin implements MapperPlugin, ActionPlugin { +import static java.util.Collections.singletonList; + +public class PercolatorPlugin extends Plugin implements MapperPlugin, ActionPlugin, SearchPlugin { private final Settings settings; @@ -56,7 +60,11 @@ public class PercolatorPlugin extends Plugin implements MapperPlugin, ActionPlug public void onModule(SearchModule module) { module.registerQuery(PercolateQueryBuilder::new, PercolateQueryBuilder::fromXContent, PercolateQueryBuilder.QUERY_NAME_FIELD); - module.registerFetchSubPhase(new PercolatorHighlightSubFetchPhase(settings, module.getHighlighters())); + } + + @Override + public List getFetchSubPhases(FetchPhaseConstructionContext context) { + return singletonList(new PercolatorHighlightSubFetchPhase(settings, context.getHighlighters())); } @Override diff --git a/modules/percolator/src/test/java/org/elasticsearch/percolator/PercolatorHighlightSubFetchPhaseTests.java b/modules/percolator/src/test/java/org/elasticsearch/percolator/PercolatorHighlightSubFetchPhaseTests.java index 0870fb2b32c..55a25768187 100644 --- a/modules/percolator/src/test/java/org/elasticsearch/percolator/PercolatorHighlightSubFetchPhaseTests.java +++ b/modules/percolator/src/test/java/org/elasticsearch/percolator/PercolatorHighlightSubFetchPhaseTests.java @@ -29,7 +29,6 @@ import org.elasticsearch.common.bytes.BytesArray; import org.elasticsearch.common.lucene.search.function.FunctionScoreQuery; import org.elasticsearch.common.lucene.search.function.RandomScoreFunction; import org.elasticsearch.common.settings.Settings; -import org.elasticsearch.search.Highlighters; import org.elasticsearch.search.highlight.SearchContextHighlight; import org.elasticsearch.search.internal.SearchContext; import org.elasticsearch.test.ESTestCase; @@ -38,6 +37,7 @@ import org.mockito.Mockito; import java.util.Arrays; import java.util.Collections; +import static java.util.Collections.emptyMap; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.nullValue; import static org.hamcrest.Matchers.sameInstance; @@ -49,7 +49,7 @@ public class PercolatorHighlightSubFetchPhaseTests extends ESTestCase { "", ctx -> null, new BytesArray("{}"), new MatchAllDocsQuery(), Mockito.mock(IndexSearcher.class), new MatchAllDocsQuery() ); PercolatorHighlightSubFetchPhase subFetchPhase = new PercolatorHighlightSubFetchPhase(Settings.EMPTY, - new Highlighters(Settings.EMPTY)); + emptyMap()); SearchContext searchContext = Mockito.mock(SearchContext.class); Mockito.when(searchContext.highlight()).thenReturn(new SearchContextHighlight(Collections.emptyList())); Mockito.when(searchContext.query()).thenReturn(new MatchAllDocsQuery()); diff --git a/test/framework/src/main/java/org/elasticsearch/test/AbstractQueryTestCase.java b/test/framework/src/main/java/org/elasticsearch/test/AbstractQueryTestCase.java index 03ee7d1f540..ed0ae4c1fbb 100644 --- a/test/framework/src/main/java/org/elasticsearch/test/AbstractQueryTestCase.java +++ b/test/framework/src/main/java/org/elasticsearch/test/AbstractQueryTestCase.java @@ -94,6 +94,7 @@ import org.elasticsearch.node.internal.InternalSettingsPreparer; import org.elasticsearch.plugins.MapperPlugin; import org.elasticsearch.plugins.Plugin; import org.elasticsearch.plugins.PluginsService; +import org.elasticsearch.plugins.SearchPlugin; import org.elasticsearch.script.Script.ScriptParseException; import org.elasticsearch.script.ScriptModule; import org.elasticsearch.script.ScriptService; @@ -866,7 +867,7 @@ public abstract class AbstractQueryTestCase> scriptSettings.addAll(pluginsService.getPluginSettings()); scriptSettings.add(InternalSettingsPlugin.VERSION_CREATED); SettingsModule settingsModule = new SettingsModule(settings, scriptSettings, pluginsService.getPluginSettingsFilter()); - searchModule = new SearchModule(settings, namedWriteableRegistry, false) { + searchModule = new SearchModule(settings, namedWriteableRegistry, false, pluginsService.filterPlugins(SearchPlugin.class)) { @Override protected void configureSearch() { // Skip me diff --git a/test/framework/src/main/java/org/elasticsearch/test/hamcrest/ElasticsearchAssertions.java b/test/framework/src/main/java/org/elasticsearch/test/hamcrest/ElasticsearchAssertions.java index 24af2b72bd1..c3993315413 100644 --- a/test/framework/src/main/java/org/elasticsearch/test/hamcrest/ElasticsearchAssertions.java +++ b/test/framework/src/main/java/org/elasticsearch/test/hamcrest/ElasticsearchAssertions.java @@ -76,6 +76,7 @@ import java.util.List; import java.util.Locale; import java.util.Set; +import static java.util.Collections.emptyList; import static org.apache.lucene.util.LuceneTestCase.random; import static org.elasticsearch.test.VersionUtils.randomVersion; import static org.hamcrest.CoreMatchers.equalTo; @@ -627,7 +628,7 @@ public class ElasticsearchAssertions { registry = ESIntegTestCase.internalCluster().getInstance(NamedWriteableRegistry.class); } else { registry = new NamedWriteableRegistry(); - new SearchModule(Settings.EMPTY, registry, false); + new SearchModule(Settings.EMPTY, registry, false, emptyList()); } assertVersionSerializable(version, streamable, registry); }