From df08854c60a2bf1402377615e9bce644e6304e0b Mon Sep 17 00:00:00 2001 From: Nik Everett Date: Mon, 28 Mar 2016 11:06:03 -0400 Subject: Remove PROTOTYPEs from suggesters Also stops using guice for suggesters at all and lots of checkstyle. --- .../org/elasticsearch/search/SearchModule.java | 22 ++- .../org/elasticsearch/search/suggest/SortBy.java | 5 +- .../elasticsearch/search/suggest/Suggester.java | 8 +- .../elasticsearch/search/suggest/Suggesters.java | 54 ++++---- .../search/suggest/SuggestionBuilder.java | 70 ++++------ .../suggest/completion/CompletionSuggester.java | 15 +- .../completion/CompletionSuggestionBuilder.java | 76 ++++------- .../completion/CompletionSuggestionContext.java | 2 +- .../search/suggest/completion/FuzzyOptions.java | 48 +++---- .../search/suggest/completion/RegexOptions.java | 36 ++--- .../completion/context/CategoryContextMapping.java | 4 +- .../completion/context/CategoryQueryContext.java | 6 +- .../suggest/completion/context/ContextMapping.java | 8 +- .../completion/context/GeoContextMapping.java | 4 +- .../completion/context/GeoQueryContext.java | 6 +- .../suggest/completion/context/QueryContext.java | 33 ----- .../suggest/phrase/DirectCandidateGenerator.java | 40 +++--- .../phrase/DirectCandidateGeneratorBuilder.java | 103 ++++++-------- .../search/suggest/phrase/Laplace.java | 31 +++-- .../search/suggest/phrase/LaplaceScorer.java | 12 +- .../suggest/phrase/LinearInterpoatingScorer.java | 4 +- .../search/suggest/phrase/LinearInterpolation.java | 41 +++--- .../search/suggest/phrase/PhraseSuggester.java | 14 +- .../suggest/phrase/PhraseSuggestionBuilder.java | 152 ++++++++++----------- .../suggest/phrase/PhraseSuggestionContext.java | 8 +- .../search/suggest/phrase/SmoothingModel.java | 8 +- .../search/suggest/phrase/StupidBackoff.java | 31 +++-- .../search/suggest/phrase/StupidBackoffScorer.java | 9 +- .../search/suggest/term/TermSuggester.java | 22 ++- .../search/suggest/term/TermSuggestion.java | 2 +- .../search/suggest/term/TermSuggestionBuilder.java | 76 +++++------ .../search/suggest/term/TermSuggestionContext.java | 2 +- 32 files changed, 421 insertions(+), 531 deletions(-) delete mode 100644 core/src/main/java/org/elasticsearch/search/suggest/completion/context/QueryContext.java (limited to 'core/src/main/java/org/elasticsearch/search') diff --git a/core/src/main/java/org/elasticsearch/search/SearchModule.java b/core/src/main/java/org/elasticsearch/search/SearchModule.java index 8756a31c44..1b69a155e1 100644 --- a/core/src/main/java/org/elasticsearch/search/SearchModule.java +++ b/core/src/main/java/org/elasticsearch/search/SearchModule.java @@ -249,7 +249,7 @@ public class SearchModule extends AbstractModule { private final Set aggParsers = new HashSet<>(); private final Set pipelineAggParsers = new HashSet<>(); private final Highlighters highlighters = new Highlighters(); - private final Suggesters suggesters = new Suggesters(); + private final Suggesters suggesters; /** * Function score parsers constructed on registration. This is ok because * they don't have any dependencies. @@ -274,6 +274,7 @@ public class SearchModule extends AbstractModule { public SearchModule(Settings settings, NamedWriteableRegistry namedWriteableRegistry) { this.settings = settings; this.namedWriteableRegistry = namedWriteableRegistry; + suggesters = new Suggesters(namedWriteableRegistry); registerBuiltinFunctionScoreParsers(); registerBuiltinQueryParsers(); @@ -286,8 +287,7 @@ public class SearchModule extends AbstractModule { } public void registerSuggester(String key, Suggester suggester) { - suggesters.registerExtension(key, suggester.getClass()); - namedWriteableRegistry.registerPrototype(SuggestionBuilder.class, suggester.getBuilderPrototype()); + suggesters.register(key, suggester); } /** @@ -337,10 +337,10 @@ public class SearchModule extends AbstractModule { protected void configure() { IndicesQueriesRegistry indicesQueriesRegistry = buildQueryParserRegistry(); bind(IndicesQueriesRegistry.class).toInstance(indicesQueriesRegistry); + bind(Suggesters.class).toInstance(suggesters); configureSearch(); configureAggs(indicesQueriesRegistry); configureHighlighters(); - configureSuggesters(); configureFetchSubPhase(); configureShapes(); } @@ -378,16 +378,6 @@ public class SearchModule extends AbstractModule { return new IndicesQueriesRegistry(settings, queryParsersMap); } - protected void configureSuggesters() { - suggesters.bind(binder()); - namedWriteableRegistry.registerPrototype(SuggestionBuilder.class, TermSuggestionBuilder.PROTOTYPE); - namedWriteableRegistry.registerPrototype(SuggestionBuilder.class, PhraseSuggestionBuilder.PROTOTYPE); - namedWriteableRegistry.registerPrototype(SuggestionBuilder.class, CompletionSuggestionBuilder.PROTOTYPE); - namedWriteableRegistry.registerPrototype(SmoothingModel.class, Laplace.PROTOTYPE); - namedWriteableRegistry.registerPrototype(SmoothingModel.class, LinearInterpolation.PROTOTYPE); - namedWriteableRegistry.registerPrototype(SmoothingModel.class, StupidBackoff.PROTOTYPE); - } - protected void configureHighlighters() { highlighters.bind(binder()); } @@ -615,4 +605,8 @@ public class SearchModule extends AbstractModule { BucketSelectorPipelineAggregator.registerStreams(); SerialDiffPipelineAggregator.registerStreams(); } + + public Suggesters getSuggesters() { + return suggesters; + } } diff --git a/core/src/main/java/org/elasticsearch/search/suggest/SortBy.java b/core/src/main/java/org/elasticsearch/search/suggest/SortBy.java index 14d46d134d..bab2b1ce61 100644 --- a/core/src/main/java/org/elasticsearch/search/suggest/SortBy.java +++ b/core/src/main/java/org/elasticsearch/search/suggest/SortBy.java @@ -36,15 +36,12 @@ public enum SortBy implements Writeable { /** Sort should first be based on document frequency, then score and then the term itself. */ FREQUENCY; - public static SortBy PROTOTYPE = SCORE; - @Override public void writeTo(final StreamOutput out) throws IOException { out.writeVInt(ordinal()); } - @Override - public SortBy readFrom(final StreamInput in) throws IOException { + public static SortBy readFromStream(final StreamInput in) throws IOException { int ordinal = in.readVInt(); if (ordinal < 0 || ordinal >= values().length) { throw new IOException("Unknown SortBy ordinal [" + ordinal + "]"); diff --git a/core/src/main/java/org/elasticsearch/search/suggest/Suggester.java b/core/src/main/java/org/elasticsearch/search/suggest/Suggester.java index 5772f2b55d..711e3d9db7 100644 --- a/core/src/main/java/org/elasticsearch/search/suggest/Suggester.java +++ b/core/src/main/java/org/elasticsearch/search/suggest/Suggester.java @@ -21,18 +21,20 @@ package org.elasticsearch.search.suggest; import org.apache.lucene.search.IndexSearcher; import org.apache.lucene.util.CharsRefBuilder; +import org.elasticsearch.common.io.stream.Writeable; +import org.elasticsearch.index.query.QueryParseContext; import java.io.IOException; -public abstract class Suggester { +public abstract class Suggester implements Writeable.Reader> { protected abstract Suggest.Suggestion> innerExecute(String name, T suggestion, IndexSearcher searcher, CharsRefBuilder spare) throws IOException; /** - * link the suggester to its corresponding {@link SuggestionBuilder} + * Read the SuggestionBuilder paired with this Suggester XContent. */ - public abstract SuggestionBuilder getBuilderPrototype(); + public abstract SuggestionBuilder innerFromXContent(QueryParseContext context) throws IOException; public Suggest.Suggestion> execute(String name, T suggestion, IndexSearcher searcher, CharsRefBuilder spare) throws IOException { 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 644d9239b8..cea00eb4ad 100644 --- a/core/src/main/java/org/elasticsearch/search/suggest/Suggesters.java +++ b/core/src/main/java/org/elasticsearch/search/suggest/Suggesters.java @@ -18,52 +18,50 @@ */ package org.elasticsearch.search.suggest; -import org.elasticsearch.common.inject.Inject; -import org.elasticsearch.common.util.ExtensionPoint; +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.Arrays; -import java.util.Collections; import java.util.HashMap; -import java.util.HashSet; import java.util.Map; /** * */ -public final class Suggesters extends ExtensionPoint.ClassMap { - private final Map parsers; +public final class Suggesters { + private final Map> suggesters = new HashMap<>(); + private final NamedWriteableRegistry namedWriteableRegistry; - public Suggesters() { - this(Collections.emptyMap()); - } + public Suggesters(NamedWriteableRegistry namedWriteableRegistry) { + this.namedWriteableRegistry = namedWriteableRegistry; + register("phrase", PhraseSuggester.INSTANCE); + register("term", TermSuggester.INSTANCE); + register("completion", CompletionSuggester.INSTANCE); - @Inject - public Suggesters(Map suggesters) { - super("suggester", Suggester.class, new HashSet<>(Arrays.asList("phrase", "term", "completion")), Suggesters.class, SuggestPhase.class); - this.parsers = Collections.unmodifiableMap(addBuildIns(suggesters)); + // 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); } - private static Map addBuildIns(Map suggesters) { - final Map map = new HashMap<>(); - map.put("phrase", PhraseSuggester.PROTOTYPE); - map.put("term", TermSuggester.PROTOTYPE); - map.put("completion", CompletionSuggester.PROTOTYPE); - map.putAll(suggesters); - return map; + 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 SuggestionBuilder getSuggestionPrototype(String suggesterName) { - Suggester suggester = parsers.get(suggesterName); + public Suggester getSuggester(String suggesterName) { + Suggester suggester = suggesters.get(suggesterName); if (suggester == null) { throw new IllegalArgumentException("suggester with name [" + suggesterName + "] not supported"); } - SuggestionBuilder suggestParser = suggester.getBuilderPrototype(); - if (suggestParser == null) { - throw new IllegalArgumentException("suggester with name [" + suggesterName + "] not supported"); - } - return suggestParser; + return suggester; } } diff --git a/core/src/main/java/org/elasticsearch/search/suggest/SuggestionBuilder.java b/core/src/main/java/org/elasticsearch/search/suggest/SuggestionBuilder.java index 29f50649cb..aaf6d5ae6d 100644 --- a/core/src/main/java/org/elasticsearch/search/suggest/SuggestionBuilder.java +++ b/core/src/main/java/org/elasticsearch/search/suggest/SuggestionBuilder.java @@ -86,6 +86,34 @@ public abstract class SuggestionBuilder> extends shardSize = in.shardSize; } + /** + * Read from a stream. + */ + protected SuggestionBuilder(StreamInput in) throws IOException { + field = in.readString(); + text = in.readOptionalString(); + prefix = in.readOptionalString(); + regex = in.readOptionalString(); + analyzer = in.readOptionalString(); + size = in.readOptionalVInt(); + shardSize = in.readOptionalVInt(); + } + + @Override + public final void writeTo(StreamOutput out) throws IOException { + out.writeString(field); + out.writeOptionalString(text); + out.writeOptionalString(prefix); + out.writeOptionalString(regex); + out.writeOptionalString(analyzer); + out.writeOptionalVInt(size); + out.writeOptionalVInt(shardSize); + doWriteTo(out); + } + + protected abstract void doWriteTo(StreamOutput out) throws IOException; + + /** * Same as in {@link SuggestBuilder#setGlobalText(String)}, but in the suggestion scope. */ @@ -251,11 +279,7 @@ public abstract class SuggestionBuilder> extends throw new ParsingException(parser.getTokenLocation(), "suggestion does not support [" + currentFieldName + "]"); } } else if (token == XContentParser.Token.START_OBJECT) { - SuggestionBuilder suggestParser = suggesters.getSuggestionPrototype(currentFieldName); - if (suggestParser == null) { - throw new ParsingException(parser.getTokenLocation(), "suggestion [" + currentFieldName + "] not supported"); - } - suggestionBuilder = suggestParser.innerFromXContent(parseContext); + suggestionBuilder = suggesters.getSuggester(currentFieldName).innerFromXContent(parseContext); } } if (suggestionBuilder == null) { @@ -273,8 +297,6 @@ public abstract class SuggestionBuilder> extends return suggestionBuilder; } - protected abstract SuggestionBuilder innerFromXContent(QueryParseContext parseContext) throws IOException; - protected abstract SuggestionContext build(QueryShardContext context) throws IOException; /** @@ -340,40 +362,6 @@ public abstract class SuggestionBuilder> extends return getWriteableName(); } - @Override - public final T readFrom(StreamInput in) throws IOException { - String field = in.readString(); - T suggestionBuilder = doReadFrom(in, field); - suggestionBuilder.text = in.readOptionalString(); - suggestionBuilder.prefix = in.readOptionalString(); - suggestionBuilder.regex = in.readOptionalString(); - suggestionBuilder.analyzer = in.readOptionalString(); - suggestionBuilder.size = in.readOptionalVInt(); - suggestionBuilder.shardSize = in.readOptionalVInt(); - return suggestionBuilder; - } - - /** - * Subclass should return a new instance, reading itself from the input string - * @param in the input string to read from - * @param field the field needed for ctor or concrete suggestion - */ - protected abstract T doReadFrom(StreamInput in, String field) throws IOException; - - @Override - public final void writeTo(StreamOutput out) throws IOException { - out.writeString(field); - doWriteTo(out); - out.writeOptionalString(text); - out.writeOptionalString(prefix); - out.writeOptionalString(regex); - out.writeOptionalString(analyzer); - out.writeOptionalVInt(size); - out.writeOptionalVInt(shardSize); - } - - protected abstract void doWriteTo(StreamOutput out) throws IOException; - @Override public final boolean equals(Object obj) { if (this == obj) { diff --git a/core/src/main/java/org/elasticsearch/search/suggest/completion/CompletionSuggester.java b/core/src/main/java/org/elasticsearch/search/suggest/completion/CompletionSuggester.java index cef0a33fdd..8bf35a34b2 100644 --- a/core/src/main/java/org/elasticsearch/search/suggest/completion/CompletionSuggester.java +++ b/core/src/main/java/org/elasticsearch/search/suggest/completion/CompletionSuggester.java @@ -30,12 +30,14 @@ import org.apache.lucene.search.suggest.document.TopSuggestDocs; import org.apache.lucene.search.suggest.document.TopSuggestDocsCollector; import org.apache.lucene.util.CharsRefBuilder; import org.apache.lucene.util.PriorityQueue; +import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.text.Text; import org.elasticsearch.index.fielddata.AtomicFieldData; import org.elasticsearch.index.fielddata.ScriptDocValues; import org.elasticsearch.index.mapper.MappedFieldType; import org.elasticsearch.index.mapper.MapperService; import org.elasticsearch.index.mapper.core.CompletionFieldMapper; +import org.elasticsearch.index.query.QueryParseContext; import org.elasticsearch.index.query.QueryShardContext; import org.elasticsearch.search.suggest.Suggest; import org.elasticsearch.search.suggest.Suggester; @@ -52,7 +54,9 @@ import java.util.Set; public class CompletionSuggester extends Suggester { - public static final CompletionSuggester PROTOTYPE = new CompletionSuggester(); + public static final CompletionSuggester INSTANCE = new CompletionSuggester(); + + private CompletionSuggester() {} @Override protected Suggest.Suggestion> innerExecute(String name, @@ -267,7 +271,12 @@ public class CompletionSuggester extends Suggester } @Override - public SuggestionBuilder getBuilderPrototype() { - return CompletionSuggestionBuilder.PROTOTYPE; + public SuggestionBuilder innerFromXContent(QueryParseContext context) throws IOException { + return CompletionSuggestionBuilder.innerFromXContent(context); + } + + @Override + public SuggestionBuilder read(StreamInput in) throws IOException { + return new CompletionSuggestionBuilder(in); } } diff --git a/core/src/main/java/org/elasticsearch/search/suggest/completion/CompletionSuggestionBuilder.java b/core/src/main/java/org/elasticsearch/search/suggest/completion/CompletionSuggestionBuilder.java index ca8aad7c8a..a4d2b59844 100644 --- a/core/src/main/java/org/elasticsearch/search/suggest/completion/CompletionSuggestionBuilder.java +++ b/core/src/main/java/org/elasticsearch/search/suggest/completion/CompletionSuggestionBuilder.java @@ -40,7 +40,6 @@ import org.elasticsearch.search.suggest.SuggestionBuilder; import org.elasticsearch.search.suggest.SuggestionSearchContext.SuggestionContext; import org.elasticsearch.search.suggest.completion.context.ContextMapping; import org.elasticsearch.search.suggest.completion.context.ContextMappings; -import org.elasticsearch.search.suggest.completion.context.QueryContext; import java.io.IOException; import java.util.ArrayList; @@ -57,8 +56,6 @@ import java.util.Objects; * indexing. */ public class CompletionSuggestionBuilder extends SuggestionBuilder { - - public static final CompletionSuggestionBuilder PROTOTYPE = new CompletionSuggestionBuilder("_na_"); static final String SUGGESTION_NAME = "completion"; static final ParseField PAYLOAD_FIELD = new ParseField("payload"); static final ParseField CONTEXTS_FIELD = new ParseField("contexts", "context"); @@ -124,6 +121,26 @@ public class CompletionSuggestionBuilder extends SuggestionBuilder(); + Collections.addAll(payloadFields, in.readStringArray()); + fuzzyOptions = in.readOptionalWriteable(FuzzyOptions::new); + regexOptions = in.readOptionalWriteable(RegexOptions::new); + contextBytes = in.readOptionalBytesReference(); + } + + @Override + public void doWriteTo(StreamOutput out) throws IOException { + out.writeStringArray(payloadFields.toArray(new String[payloadFields.size()])); + out.writeOptionalWriteable(fuzzyOptions); + out.writeOptionalWriteable(regexOptions); + out.writeOptionalBytesReference(contextBytes); + } + /** * Sets the prefix to provide completions for. * The prefix gets analyzed by the suggest analyzer. @@ -188,12 +205,12 @@ public class CompletionSuggestionBuilder extends SuggestionBuilder> queryContexts) { + public CompletionSuggestionBuilder contexts(Map> queryContexts) { Objects.requireNonNull(queryContexts, "contexts must not be null"); try { XContentBuilder contentBuilder = XContentFactory.jsonBuilder(); contentBuilder.startObject(); - for (Map.Entry> contextEntry : queryContexts.entrySet()) { + for (Map.Entry> contextEntry : queryContexts.entrySet()) { contentBuilder.startArray(contextEntry.getKey()); for (ToXContent queryContext : contextEntry.getValue()) { queryContext.toXContent(contentBuilder, EMPTY_PARAMS); @@ -244,8 +261,7 @@ public class CompletionSuggestionBuilder extends SuggestionBuilder payloadFields = new ArrayList<>(numPayloadField); - for (int i = 0; i < numPayloadField; i++) { - payloadFields.add(in.readString()); - } - completionSuggestionBuilder.payloadFields = payloadFields; - } - if (in.readBoolean()) { - completionSuggestionBuilder.fuzzyOptions = FuzzyOptions.readFuzzyOptions(in); - } - if (in.readBoolean()) { - completionSuggestionBuilder.regexOptions = RegexOptions.readRegexOptions(in); - } - if (in.readBoolean()) { - completionSuggestionBuilder.contextBytes = in.readBytesReference(); - } - return completionSuggestionBuilder; - } - @Override protected boolean doEquals(CompletionSuggestionBuilder other) { return Objects.equals(payloadFields, other.payloadFields) && diff --git a/core/src/main/java/org/elasticsearch/search/suggest/completion/CompletionSuggestionContext.java b/core/src/main/java/org/elasticsearch/search/suggest/completion/CompletionSuggestionContext.java index f9f948a551..1941bc9fb8 100644 --- a/core/src/main/java/org/elasticsearch/search/suggest/completion/CompletionSuggestionContext.java +++ b/core/src/main/java/org/elasticsearch/search/suggest/completion/CompletionSuggestionContext.java @@ -36,7 +36,7 @@ import java.util.Map; public class CompletionSuggestionContext extends SuggestionSearchContext.SuggestionContext { protected CompletionSuggestionContext(QueryShardContext shardContext) { - super(CompletionSuggester.PROTOTYPE, shardContext); + super(CompletionSuggester.INSTANCE, shardContext); } private CompletionFieldMapper.CompletionFieldType fieldType; diff --git a/core/src/main/java/org/elasticsearch/search/suggest/completion/FuzzyOptions.java b/core/src/main/java/org/elasticsearch/search/suggest/completion/FuzzyOptions.java index 8f05be0469..ed2efdf456 100644 --- a/core/src/main/java/org/elasticsearch/search/suggest/completion/FuzzyOptions.java +++ b/core/src/main/java/org/elasticsearch/search/suggest/completion/FuzzyOptions.java @@ -89,7 +89,26 @@ public class FuzzyOptions implements ToXContent, Writeable { this.maxDeterminizedStates = maxDeterminizedStates; } - private FuzzyOptions() { + /** + * Read from a stream. + */ + FuzzyOptions(StreamInput in) throws IOException { + transpositions = in.readBoolean(); + unicodeAware = in.readBoolean(); + editDistance = in.readVInt(); + fuzzyMinLength = in.readVInt(); + fuzzyPrefixLength = in.readVInt(); + maxDeterminizedStates = in.readVInt(); + } + + @Override + public void writeTo(StreamOutput out) throws IOException { + out.writeBoolean(transpositions); + out.writeBoolean(unicodeAware); + out.writeVInt(editDistance); + out.writeVInt(fuzzyMinLength); + out.writeVInt(fuzzyPrefixLength); + out.writeVInt(maxDeterminizedStates); } static FuzzyOptions parse(XContentParser parser) throws IOException { @@ -185,33 +204,6 @@ public class FuzzyOptions implements ToXContent, Writeable { return builder; } - public static FuzzyOptions readFuzzyOptions(StreamInput in) throws IOException { - FuzzyOptions fuzzyOptions = new FuzzyOptions(); - fuzzyOptions.readFrom(in); - return fuzzyOptions; - } - - @Override - public FuzzyOptions readFrom(StreamInput in) throws IOException { - this.transpositions = in.readBoolean(); - this.unicodeAware = in.readBoolean(); - this.editDistance = in.readVInt(); - this.fuzzyMinLength = in.readVInt(); - this.fuzzyPrefixLength = in.readVInt(); - this.maxDeterminizedStates = in.readVInt(); - return this; - } - - @Override - public void writeTo(StreamOutput out) throws IOException { - out.writeBoolean(transpositions); - out.writeBoolean(unicodeAware); - out.writeVInt(editDistance); - out.writeVInt(fuzzyMinLength); - out.writeVInt(fuzzyPrefixLength); - out.writeVInt(maxDeterminizedStates); - } - /** * Options for fuzzy queries */ diff --git a/core/src/main/java/org/elasticsearch/search/suggest/completion/RegexOptions.java b/core/src/main/java/org/elasticsearch/search/suggest/completion/RegexOptions.java index 8503dbdf46..58464cddee 100644 --- a/core/src/main/java/org/elasticsearch/search/suggest/completion/RegexOptions.java +++ b/core/src/main/java/org/elasticsearch/search/suggest/completion/RegexOptions.java @@ -67,14 +67,25 @@ public class RegexOptions implements ToXContent, Writeable { private int flagsValue; private int maxDeterminizedStates; - private RegexOptions() { - } - private RegexOptions(int flagsValue, int maxDeterminizedStates) { this.flagsValue = flagsValue; this.maxDeterminizedStates = maxDeterminizedStates; } + /** + * Read from a stream. + */ + RegexOptions(StreamInput in) throws IOException { + this.flagsValue = in.readVInt(); + this.maxDeterminizedStates = in.readVInt(); + } + + @Override + public void writeTo(StreamOutput out) throws IOException { + out.writeVInt(flagsValue); + out.writeVInt(maxDeterminizedStates); + } + /** * Returns internal regular expression syntax flag value * see {@link RegexpFlag#value()} @@ -126,25 +137,6 @@ public class RegexOptions implements ToXContent, Writeable { return builder; } - public static RegexOptions readRegexOptions(StreamInput in) throws IOException { - RegexOptions regexOptions = new RegexOptions(); - regexOptions.readFrom(in); - return regexOptions; - } - - @Override - public RegexOptions readFrom(StreamInput in) throws IOException { - this.flagsValue = in.readVInt(); - this.maxDeterminizedStates = in.readVInt(); - return this; - } - - @Override - public void writeTo(StreamOutput out) throws IOException { - out.writeVInt(flagsValue); - out.writeVInt(maxDeterminizedStates); - } - /** * Options for regular expression queries */ diff --git a/core/src/main/java/org/elasticsearch/search/suggest/completion/context/CategoryContextMapping.java b/core/src/main/java/org/elasticsearch/search/suggest/completion/context/CategoryContextMapping.java index c9cb165aef..1931c4a9e0 100644 --- a/core/src/main/java/org/elasticsearch/search/suggest/completion/context/CategoryContextMapping.java +++ b/core/src/main/java/org/elasticsearch/search/suggest/completion/context/CategoryContextMapping.java @@ -139,8 +139,8 @@ public class CategoryContextMapping extends ContextMapping } @Override - protected CategoryQueryContext prototype() { - return CategoryQueryContext.PROTOTYPE; + protected CategoryQueryContext fromXContent(XContentParser parser) throws IOException { + return CategoryQueryContext.fromXContent(parser); } /** diff --git a/core/src/main/java/org/elasticsearch/search/suggest/completion/context/CategoryQueryContext.java b/core/src/main/java/org/elasticsearch/search/suggest/completion/context/CategoryQueryContext.java index a164faff8b..2e47795010 100644 --- a/core/src/main/java/org/elasticsearch/search/suggest/completion/context/CategoryQueryContext.java +++ b/core/src/main/java/org/elasticsearch/search/suggest/completion/context/CategoryQueryContext.java @@ -22,6 +22,7 @@ package org.elasticsearch.search.suggest.completion.context; import org.elasticsearch.ElasticsearchParseException; import org.elasticsearch.common.ParseField; import org.elasticsearch.common.xcontent.ObjectParser; +import org.elasticsearch.common.xcontent.ToXContent; import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentParser; @@ -35,7 +36,7 @@ import static org.elasticsearch.search.suggest.completion.context.CategoryContex /** * Defines the query context for {@link CategoryContextMapping} */ -public final class CategoryQueryContext implements QueryContext { +public final class CategoryQueryContext implements ToXContent { public static final String NAME = "category"; public static final CategoryQueryContext PROTOTYPE = new CategoryQueryContext("", 1, false); @@ -102,8 +103,7 @@ public final class CategoryQueryContext implements QueryContext { CATEGORY_PARSER.declareBoolean(Builder::setPrefix, new ParseField(CONTEXT_PREFIX)); } - @Override - public CategoryQueryContext fromXContext(XContentParser parser) throws IOException { + public static CategoryQueryContext fromXContent(XContentParser parser) throws IOException { XContentParser.Token token = parser.currentToken(); Builder builder = builder(); if (token == XContentParser.Token.START_OBJECT) { diff --git a/core/src/main/java/org/elasticsearch/search/suggest/completion/context/ContextMapping.java b/core/src/main/java/org/elasticsearch/search/suggest/completion/context/ContextMapping.java index 959a749a85..cb445b1770 100644 --- a/core/src/main/java/org/elasticsearch/search/suggest/completion/context/ContextMapping.java +++ b/core/src/main/java/org/elasticsearch/search/suggest/completion/context/ContextMapping.java @@ -40,7 +40,7 @@ import java.util.Set; * * Implementations have to define how contexts are parsed at query/index time */ -public abstract class ContextMapping implements ToXContent { +public abstract class ContextMapping implements ToXContent { public static final String FIELD_TYPE = "type"; public static final String FIELD_NAME = "name"; @@ -99,7 +99,7 @@ public abstract class ContextMapping implements ToXConte /** * Prototype for the query context */ - protected abstract T prototype(); + protected abstract T fromXContent(XContentParser parser) throws IOException; /** * Parses query contexts for this mapper @@ -108,10 +108,10 @@ public abstract class ContextMapping implements ToXConte List queryContexts = new ArrayList<>(); Token token = parser.nextToken(); if (token == Token.START_OBJECT || token == Token.VALUE_STRING) { - queryContexts.add((T) prototype().fromXContext(parser)); + queryContexts.add(fromXContent(parser)); } else if (token == Token.START_ARRAY) { while (parser.nextToken() != Token.END_ARRAY) { - queryContexts.add((T) prototype().fromXContext(parser)); + queryContexts.add(fromXContent(parser)); } } return toInternalQueryContexts(queryContexts); diff --git a/core/src/main/java/org/elasticsearch/search/suggest/completion/context/GeoContextMapping.java b/core/src/main/java/org/elasticsearch/search/suggest/completion/context/GeoContextMapping.java index 41d78e7535..393f798c85 100644 --- a/core/src/main/java/org/elasticsearch/search/suggest/completion/context/GeoContextMapping.java +++ b/core/src/main/java/org/elasticsearch/search/suggest/completion/context/GeoContextMapping.java @@ -223,8 +223,8 @@ public class GeoContextMapping extends ContextMapping { } @Override - protected GeoQueryContext prototype() { - return GeoQueryContext.PROTOTYPE; + protected GeoQueryContext fromXContent(XContentParser parser) throws IOException { + return GeoQueryContext.fromXContent(parser); } /** diff --git a/core/src/main/java/org/elasticsearch/search/suggest/completion/context/GeoQueryContext.java b/core/src/main/java/org/elasticsearch/search/suggest/completion/context/GeoQueryContext.java index 913702c18d..43873724c0 100644 --- a/core/src/main/java/org/elasticsearch/search/suggest/completion/context/GeoQueryContext.java +++ b/core/src/main/java/org/elasticsearch/search/suggest/completion/context/GeoQueryContext.java @@ -24,6 +24,7 @@ import org.elasticsearch.common.ParseField; import org.elasticsearch.common.geo.GeoPoint; import org.elasticsearch.common.geo.GeoUtils; import org.elasticsearch.common.xcontent.ObjectParser; +import org.elasticsearch.common.xcontent.ToXContent; import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentParser; @@ -40,7 +41,7 @@ import static org.elasticsearch.search.suggest.completion.context.GeoContextMapp /** * Defines the query context for {@link GeoContextMapping} */ -public final class GeoQueryContext implements QueryContext { +public final class GeoQueryContext implements ToXContent { public static final String NAME = "geo"; public static final GeoQueryContext PROTOTYPE = new GeoQueryContext(null, 1, 12, Collections.emptyList()); @@ -123,8 +124,7 @@ public final class GeoQueryContext implements QueryContext { GEO_CONTEXT_PARSER.declareDouble(GeoQueryContext.Builder::setLon, new ParseField("lon")); } - @Override - public GeoQueryContext fromXContext(XContentParser parser) throws IOException { + public static GeoQueryContext fromXContent(XContentParser parser) throws IOException { XContentParser.Token token = parser.currentToken(); GeoQueryContext.Builder builder = new Builder(); if (token == XContentParser.Token.START_OBJECT) { diff --git a/core/src/main/java/org/elasticsearch/search/suggest/completion/context/QueryContext.java b/core/src/main/java/org/elasticsearch/search/suggest/completion/context/QueryContext.java deleted file mode 100644 index 9d96bf8144..0000000000 --- a/core/src/main/java/org/elasticsearch/search/suggest/completion/context/QueryContext.java +++ /dev/null @@ -1,33 +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.suggest.completion.context; - -import org.elasticsearch.common.xcontent.ToXContent; -import org.elasticsearch.common.xcontent.XContentParser; - -import java.io.IOException; - -/** - * Interface for serializing/de-serializing completion query context - */ -public interface QueryContext extends ToXContent { - - QueryContext fromXContext(XContentParser parser) throws IOException; -} diff --git a/core/src/main/java/org/elasticsearch/search/suggest/phrase/DirectCandidateGenerator.java b/core/src/main/java/org/elasticsearch/search/suggest/phrase/DirectCandidateGenerator.java index a454735ae1..58dbff64e8 100644 --- a/core/src/main/java/org/elasticsearch/search/suggest/phrase/DirectCandidateGenerator.java +++ b/core/src/main/java/org/elasticsearch/search/suggest/phrase/DirectCandidateGenerator.java @@ -40,8 +40,11 @@ import java.util.HashSet; import java.util.List; import java.util.Set; -//TODO public for tests -public final class DirectCandidateGenerator extends CandidateGenerator { +import static java.lang.Math.log10; +import static java.lang.Math.max; +import static java.lang.Math.round; + +final class DirectCandidateGenerator extends CandidateGenerator { private final DirectSpellChecker spellchecker; private final String field; @@ -59,12 +62,13 @@ public final class DirectCandidateGenerator extends CandidateGenerator { private final BytesRefBuilder byteSpare = new BytesRefBuilder(); private final int numCandidates; - public DirectCandidateGenerator(DirectSpellChecker spellchecker, String field, SuggestMode suggestMode, IndexReader reader, double nonErrorLikelihood, int numCandidates) throws IOException { - this(spellchecker, field, suggestMode, reader, nonErrorLikelihood, numCandidates, null, null, MultiFields.getTerms(reader, field)); + public DirectCandidateGenerator(DirectSpellChecker spellchecker, String field, SuggestMode suggestMode, IndexReader reader, + double nonErrorLikelihood, int numCandidates) throws IOException { + this(spellchecker, field, suggestMode, reader, nonErrorLikelihood, numCandidates, null, null, MultiFields.getTerms(reader, field)); } - - public DirectCandidateGenerator(DirectSpellChecker spellchecker, String field, SuggestMode suggestMode, IndexReader reader, double nonErrorLikelihood, int numCandidates, Analyzer preFilter, Analyzer postFilter, Terms terms) throws IOException { + public DirectCandidateGenerator(DirectSpellChecker spellchecker, String field, SuggestMode suggestMode, IndexReader reader, + double nonErrorLikelihood, int numCandidates, Analyzer preFilter, Analyzer postFilter, Terms terms) throws IOException { if (terms == null) { throw new IllegalArgumentException("generator field [" + field + "] doesn't exist"); } @@ -113,9 +117,6 @@ public final class DirectCandidateGenerator extends CandidateGenerator { return field; } - /* (non-Javadoc) - * @see org.elasticsearch.search.suggest.phrase.CandidateGenerator#drawCandidates(org.elasticsearch.search.suggest.phrase.DirectCandidateGenerator.CandidateSet, int) - */ @Override public CandidateSet drawCandidates(CandidateSet set) throws IOException { Candidate original = set.originalTerm; @@ -127,7 +128,8 @@ public final class DirectCandidateGenerator extends CandidateGenerator { for (int i = 0; i < suggestSimilar.length; i++) { SuggestWord suggestWord = suggestSimilar[i]; BytesRef candidate = new BytesRef(suggestWord.string); - postFilter(new Candidate(candidate, internalFrequency(candidate), suggestWord.score, score(suggestWord.freq, suggestWord.score, dictSize), false), spare, byteSpare, candidates); + postFilter(new Candidate(candidate, internalFrequency(candidate), suggestWord.score, + score(suggestWord.freq, suggestWord.score, dictSize), false), spare, byteSpare, candidates); } set.addCandidates(candidates); return set; @@ -148,7 +150,8 @@ public final class DirectCandidateGenerator extends CandidateGenerator { return result.get(); } - protected void postFilter(final Candidate candidate, final CharsRefBuilder spare, BytesRefBuilder byteSpare, final List candidates) throws IOException { + protected void postFilter(final Candidate candidate, final CharsRefBuilder spare, BytesRefBuilder byteSpare, + final List candidates) throws IOException { if (postFilter == null) { candidates.add(candidate); } else { @@ -163,9 +166,11 @@ public final class DirectCandidateGenerator extends CandidateGenerator { // We should not use frequency(term) here because it will analyze the term again // If preFilter and postFilter are the same analyzer it would fail. long freq = internalFrequency(term); - candidates.add(new Candidate(result.toBytesRef(), freq, candidate.stringDistance, score(candidate.frequency, candidate.stringDistance, dictSize), false)); + candidates.add(new Candidate(result.toBytesRef(), freq, candidate.stringDistance, + score(candidate.frequency, candidate.stringDistance, dictSize), false)); } else { - candidates.add(new Candidate(result.toBytesRef(), candidate.frequency, nonErrorLikelihood, score(candidate.frequency, candidate.stringDistance, dictSize), false)); + candidates.add(new Candidate(result.toBytesRef(), candidate.frequency, nonErrorLikelihood, + score(candidate.frequency, candidate.stringDistance, dictSize), false)); } } }, spare); @@ -178,7 +183,7 @@ public final class DirectCandidateGenerator extends CandidateGenerator { protected long thresholdFrequency(long termFrequency, long dictionarySize) { if (termFrequency > 0) { - return Math.max(0, Math.round(termFrequency * (Math.log10(termFrequency - frequencyPlateau) * (1.0 / Math.log10(logBase))) + 1)); + return max(0, round(termFrequency * (log10(termFrequency - frequencyPlateau) * (1.0 / log10(logBase))) + 1)); } return 0; @@ -232,8 +237,11 @@ public final class DirectCandidateGenerator extends CandidateGenerator { @Override public String toString() { - return "Candidate [term=" + term.utf8ToString() + ", stringDistance=" + stringDistance + ", score=" + score + ", frequency=" + frequency + - (userInput ? ", userInput" : "" ) + "]"; + return "Candidate [term=" + term.utf8ToString() + + ", stringDistance=" + stringDistance + + ", score=" + score + + ", frequency=" + frequency + + (userInput ? ", userInput" : "") + "]"; } @Override diff --git a/core/src/main/java/org/elasticsearch/search/suggest/phrase/DirectCandidateGeneratorBuilder.java b/core/src/main/java/org/elasticsearch/search/suggest/phrase/DirectCandidateGeneratorBuilder.java index f6a94314f5..d2fee7ccb3 100644 --- a/core/src/main/java/org/elasticsearch/search/suggest/phrase/DirectCandidateGeneratorBuilder.java +++ b/core/src/main/java/org/elasticsearch/search/suggest/phrase/DirectCandidateGeneratorBuilder.java @@ -44,7 +44,6 @@ public final class DirectCandidateGeneratorBuilder implements CandidateGenerator { private static final String TYPE = "direct_generator"; - static final DirectCandidateGeneratorBuilder PROTOTYPE = new DirectCandidateGeneratorBuilder("_na_"); static final ParseField DIRECT_GENERATOR_FIELD = new ParseField(TYPE); static final ParseField FIELDNAME_FIELD = new ParseField("field"); @@ -108,6 +107,44 @@ public final class DirectCandidateGeneratorBuilder return generator; } + /** + * Read from a stream. + */ + public DirectCandidateGeneratorBuilder(StreamInput in) throws IOException { + field = in.readString(); + suggestMode = in.readOptionalString(); + accuracy = in.readOptionalFloat(); + size = in.readOptionalVInt(); + sort = in.readOptionalString(); + stringDistance = in.readOptionalString(); + maxEdits = in.readOptionalVInt(); + maxInspections = in.readOptionalVInt(); + maxTermFreq = in.readOptionalFloat(); + prefixLength = in.readOptionalVInt(); + minWordLength = in.readOptionalVInt(); + minDocFreq = in.readOptionalFloat(); + preFilter = in.readOptionalString(); + postFilter = in.readOptionalString(); + } + + @Override + public void writeTo(StreamOutput out) throws IOException { + out.writeString(field); + out.writeOptionalString(suggestMode); + out.writeOptionalFloat(accuracy); + out.writeOptionalVInt(size); + out.writeOptionalString(sort); + out.writeOptionalString(stringDistance); + out.writeOptionalVInt(maxEdits); + out.writeOptionalVInt(maxInspections); + out.writeOptionalFloat(maxTermFreq); + out.writeOptionalVInt(prefixLength); + out.writeOptionalVInt(minWordLength); + out.writeOptionalFloat(minDocFreq); + out.writeOptionalString(preFilter); + out.writeOptionalString(postFilter); + } + /** * The global suggest mode controls what suggested terms are included or * controls for what suggest text tokens, terms should be suggested for. @@ -334,15 +371,11 @@ public final class DirectCandidateGeneratorBuilder PARSER.declareInt((tp, i) -> tp.v2().prefixLength(i), PREFIX_LENGTH_FIELD); } - @Override - public DirectCandidateGeneratorBuilder fromXContent(QueryParseContext parseContext) throws IOException { + public static DirectCandidateGeneratorBuilder fromXContent(QueryParseContext parseContext) throws IOException { DirectCandidateGeneratorBuilder tempGenerator = new DirectCandidateGeneratorBuilder("_na_"); - Set tmpFieldName = new HashSet<>(1); // bucket for the field - // name, needed as - // constructor arg - // later - PARSER.parse(parseContext.parser(), - new Tuple, DirectCandidateGeneratorBuilder>(tmpFieldName, tempGenerator)); + // bucket for the field name, needed as constructor arg later + Set tmpFieldName = new HashSet<>(1); + PARSER.parse(parseContext.parser(), new Tuple, DirectCandidateGeneratorBuilder>(tmpFieldName, tempGenerator)); if (tmpFieldName.size() != 1) { throw new IllegalArgumentException("[" + TYPE + "] expects exactly one field parameter, but found " + tmpFieldName); } @@ -405,58 +438,6 @@ public final class DirectCandidateGeneratorBuilder } } - @Override - public DirectCandidateGeneratorBuilder readFrom(StreamInput in) throws IOException { - DirectCandidateGeneratorBuilder cg = new DirectCandidateGeneratorBuilder(in.readString()); - cg.suggestMode = in.readOptionalString(); - if (in.readBoolean()) { - cg.accuracy = in.readFloat(); - } - cg.size = in.readOptionalVInt(); - cg.sort = in.readOptionalString(); - cg.stringDistance = in.readOptionalString(); - cg.maxEdits = in.readOptionalVInt(); - cg.maxInspections = in.readOptionalVInt(); - if (in.readBoolean()) { - cg.maxTermFreq = in.readFloat(); - } - cg.prefixLength = in.readOptionalVInt(); - cg.minWordLength = in.readOptionalVInt(); - if (in.readBoolean()) { - cg.minDocFreq = in.readFloat(); - } - cg.preFilter = in.readOptionalString(); - cg.postFilter = in.readOptionalString(); - return cg; - } - - @Override - public void writeTo(StreamOutput out) throws IOException { - out.writeString(field); - out.writeOptionalString(suggestMode); - out.writeBoolean(accuracy != null); - if (accuracy != null) { - out.writeFloat(accuracy); - } - out.writeOptionalVInt(size); - out.writeOptionalString(sort); - out.writeOptionalString(stringDistance); - out.writeOptionalVInt(maxEdits); - out.writeOptionalVInt(maxInspections); - out.writeBoolean(maxTermFreq != null); - if (maxTermFreq != null) { - out.writeFloat(maxTermFreq); - } - out.writeOptionalVInt(prefixLength); - out.writeOptionalVInt(minWordLength); - out.writeBoolean(minDocFreq != null); - if (minDocFreq != null) { - out.writeFloat(minDocFreq); - } - out.writeOptionalString(preFilter); - out.writeOptionalString(postFilter); - } - @Override public final int hashCode() { return Objects.hash(field, preFilter, postFilter, suggestMode, accuracy, diff --git a/core/src/main/java/org/elasticsearch/search/suggest/phrase/Laplace.java b/core/src/main/java/org/elasticsearch/search/suggest/phrase/Laplace.java index e11a920f96..15eb759f2a 100644 --- a/core/src/main/java/org/elasticsearch/search/suggest/phrase/Laplace.java +++ b/core/src/main/java/org/elasticsearch/search/suggest/phrase/Laplace.java @@ -44,15 +44,15 @@ import java.util.Objects; *

*/ public final class Laplace extends SmoothingModel { - private double alpha = DEFAULT_LAPLACE_ALPHA; - private static final String NAME = "laplace"; + public static final String NAME = "laplace"; private static final ParseField ALPHA_FIELD = new ParseField("alpha"); static final ParseField PARSE_FIELD = new ParseField(NAME); /** * Default alpha parameter for laplace smoothing */ public static final double DEFAULT_LAPLACE_ALPHA = 0.5; - public static final Laplace PROTOTYPE = new Laplace(DEFAULT_LAPLACE_ALPHA); + + private double alpha = DEFAULT_LAPLACE_ALPHA; /** * Creates a Laplace smoothing model. @@ -62,6 +62,18 @@ public final class Laplace extends SmoothingModel { this.alpha = alpha; } + /** + * Read from a stream. + */ + public Laplace(StreamInput in) throws IOException { + alpha = in.readDouble(); + } + + @Override + public void writeTo(StreamOutput out) throws IOException { + out.writeDouble(alpha); + } + /** * @return the laplace model alpha parameter */ @@ -80,16 +92,6 @@ public final class Laplace extends SmoothingModel { return NAME; } - @Override - public void writeTo(StreamOutput out) throws IOException { - out.writeDouble(alpha); - } - - @Override - public SmoothingModel readFrom(StreamInput in) throws IOException { - return new Laplace(in.readDouble()); - } - @Override protected boolean doEquals(SmoothingModel other) { Laplace otherModel = (Laplace) other; @@ -101,8 +103,7 @@ public final class Laplace extends SmoothingModel { return Objects.hash(alpha); } - @Override - public SmoothingModel innerFromXContent(QueryParseContext parseContext) throws IOException { + public static SmoothingModel innerFromXContent(QueryParseContext parseContext) throws IOException { XContentParser parser = parseContext.parser(); XContentParser.Token token; String fieldName = null; diff --git a/core/src/main/java/org/elasticsearch/search/suggest/phrase/LaplaceScorer.java b/core/src/main/java/org/elasticsearch/search/suggest/phrase/LaplaceScorer.java index 678f3082ba..6b6301b49a 100644 --- a/core/src/main/java/org/elasticsearch/search/suggest/phrase/LaplaceScorer.java +++ b/core/src/main/java/org/elasticsearch/search/suggest/phrase/LaplaceScorer.java @@ -25,19 +25,11 @@ import org.elasticsearch.search.suggest.SuggestUtils; import org.elasticsearch.search.suggest.phrase.DirectCandidateGenerator.Candidate; import java.io.IOException; -//TODO public for tests -public final class LaplaceScorer extends WordScorer { - - public static final WordScorerFactory FACTORY = new WordScorer.WordScorerFactory() { - @Override - public WordScorer newScorer(IndexReader reader, Terms terms, String field, double realWordLikelyhood, BytesRef separator) throws IOException { - return new LaplaceScorer(reader, terms, field, realWordLikelyhood, separator, 0.5); - } - }; +final class LaplaceScorer extends WordScorer { private double alpha; - public LaplaceScorer(IndexReader reader, Terms terms, String field, + LaplaceScorer(IndexReader reader, Terms terms, String field, double realWordLikelyhood, BytesRef separator, double alpha) throws IOException { super(reader, terms, field, realWordLikelyhood, separator); this.alpha = alpha; diff --git a/core/src/main/java/org/elasticsearch/search/suggest/phrase/LinearInterpoatingScorer.java b/core/src/main/java/org/elasticsearch/search/suggest/phrase/LinearInterpoatingScorer.java index 368d461fc5..f369523167 100644 --- a/core/src/main/java/org/elasticsearch/search/suggest/phrase/LinearInterpoatingScorer.java +++ b/core/src/main/java/org/elasticsearch/search/suggest/phrase/LinearInterpoatingScorer.java @@ -33,8 +33,8 @@ public final class LinearInterpoatingScorer extends WordScorer { private final double bigramLambda; private final double trigramLambda; - public LinearInterpoatingScorer(IndexReader reader, Terms terms, String field, double realWordLikelyhood, BytesRef separator, double trigramLambda, double bigramLambda, double unigramLambda) - throws IOException { + public LinearInterpoatingScorer(IndexReader reader, Terms terms, String field, double realWordLikelyhood, BytesRef separator, + double trigramLambda, double bigramLambda, double unigramLambda) throws IOException { super(reader, terms, field, realWordLikelyhood, separator); double sum = unigramLambda + bigramLambda + trigramLambda; this.unigramLambda = unigramLambda / sum; diff --git a/core/src/main/java/org/elasticsearch/search/suggest/phrase/LinearInterpolation.java b/core/src/main/java/org/elasticsearch/search/suggest/phrase/LinearInterpolation.java index b94ea333fd..8021edcc78 100644 --- a/core/src/main/java/org/elasticsearch/search/suggest/phrase/LinearInterpolation.java +++ b/core/src/main/java/org/elasticsearch/search/suggest/phrase/LinearInterpolation.java @@ -45,16 +45,16 @@ import java.util.Objects; *

*/ public final class LinearInterpolation extends SmoothingModel { - private static final String NAME = "linear"; - public static final LinearInterpolation PROTOTYPE = new LinearInterpolation(0.8, 0.1, 0.1); - private final double trigramLambda; - private final double bigramLambda; - private final double unigramLambda; + public static final String NAME = "linear"; static final ParseField PARSE_FIELD = new ParseField(NAME); private static final ParseField TRIGRAM_FIELD = new ParseField("trigram_lambda"); private static final ParseField BIGRAM_FIELD = new ParseField("bigram_lambda"); private static final ParseField UNIGRAM_FIELD = new ParseField("unigram_lambda"); + private final double trigramLambda; + private final double bigramLambda; + private final double unigramLambda; + /** * Creates a linear interpolation smoothing model. * @@ -77,6 +77,22 @@ public final class LinearInterpolation extends SmoothingModel { this.unigramLambda = unigramLambda; } + /** + * Read from a stream. + */ + public LinearInterpolation(StreamInput in) throws IOException { + trigramLambda = in.readDouble(); + bigramLambda = in.readDouble(); + unigramLambda = in.readDouble(); + } + + @Override + public void writeTo(StreamOutput out) throws IOException { + out.writeDouble(trigramLambda); + out.writeDouble(bigramLambda); + out.writeDouble(unigramLambda); + } + public double getTrigramLambda() { return this.trigramLambda; } @@ -102,18 +118,6 @@ public final class LinearInterpolation extends SmoothingModel { return NAME; } - @Override - public void writeTo(StreamOutput out) throws IOException { - out.writeDouble(trigramLambda); - out.writeDouble(bigramLambda); - out.writeDouble(unigramLambda); - } - - @Override - public LinearInterpolation readFrom(StreamInput in) throws IOException { - return new LinearInterpolation(in.readDouble(), in.readDouble(), in.readDouble()); - } - @Override protected boolean doEquals(SmoothingModel other) { final LinearInterpolation otherModel = (LinearInterpolation) other; @@ -127,8 +131,7 @@ public final class LinearInterpolation extends SmoothingModel { return Objects.hash(trigramLambda, bigramLambda, unigramLambda); } - @Override - public LinearInterpolation innerFromXContent(QueryParseContext parseContext) throws IOException { + public static LinearInterpolation innerFromXContent(QueryParseContext parseContext) throws IOException { XContentParser parser = parseContext.parser(); XContentParser.Token token; String fieldName = null; diff --git a/core/src/main/java/org/elasticsearch/search/suggest/phrase/PhraseSuggester.java b/core/src/main/java/org/elasticsearch/search/suggest/phrase/PhraseSuggester.java index 14bced639f..11a0c10ee0 100644 --- a/core/src/main/java/org/elasticsearch/search/suggest/phrase/PhraseSuggester.java +++ b/core/src/main/java/org/elasticsearch/search/suggest/phrase/PhraseSuggester.java @@ -29,9 +29,11 @@ import org.apache.lucene.util.BytesRef; import org.apache.lucene.util.BytesRefBuilder; import org.apache.lucene.util.CharsRefBuilder; import org.elasticsearch.common.bytes.BytesReference; +import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.lucene.Lucene; import org.elasticsearch.common.text.Text; import org.elasticsearch.index.query.ParsedQuery; +import org.elasticsearch.index.query.QueryParseContext; import org.elasticsearch.script.CompiledScript; import org.elasticsearch.script.ExecutableScript; import org.elasticsearch.script.ScriptService; @@ -53,7 +55,9 @@ public final class PhraseSuggester extends Suggester { private final BytesRef SEPARATOR = new BytesRef(" "); private static final String SUGGESTION_TEMPLATE_VAR_NAME = "suggestion"; - public static final PhraseSuggester PROTOTYPE = new PhraseSuggester(); + public static final PhraseSuggester INSTANCE = new PhraseSuggester(); + + private PhraseSuggester() {} /* * More Ideas: @@ -144,8 +148,12 @@ public final class PhraseSuggester extends Suggester { } @Override - public SuggestionBuilder getBuilderPrototype() { - return PhraseSuggestionBuilder.PROTOTYPE; + public SuggestionBuilder innerFromXContent(QueryParseContext context) throws IOException { + return PhraseSuggestionBuilder.innerFromXContent(context); } + @Override + public SuggestionBuilder read(StreamInput in) throws IOException { + return new PhraseSuggestionBuilder(in); + } } diff --git a/core/src/main/java/org/elasticsearch/search/suggest/phrase/PhraseSuggestionBuilder.java b/core/src/main/java/org/elasticsearch/search/suggest/phrase/PhraseSuggestionBuilder.java index a4793dfbda..299c57d8d2 100644 --- a/core/src/main/java/org/elasticsearch/search/suggest/phrase/PhraseSuggestionBuilder.java +++ b/core/src/main/java/org/elasticsearch/search/suggest/phrase/PhraseSuggestionBuilder.java @@ -60,8 +60,6 @@ public class PhraseSuggestionBuilder extends SuggestionBuilder generatorsList = new ArrayList<>(numberOfGenerators); + for (int g = 0; g < numberOfGenerators; g++) { + DirectCandidateGeneratorBuilder generator = new DirectCandidateGeneratorBuilder(in); + generatorsList.add(generator); + } + generators.put(type, generatorsList); + } + } + + @Override + public void doWriteTo(StreamOutput out) throws IOException { + out.writeFloat(maxErrors); + out.writeFloat(realWordErrorLikelihood); + out.writeFloat(confidence); + out.writeOptionalVInt(gramSize); + boolean hasModel = model != null; + out.writeBoolean(hasModel); + if (hasModel) { + out.writePhraseSuggestionSmoothingModel(model); + } + out.writeBoolean(forceUnigrams); + out.writeVInt(tokenLimit); + out.writeOptionalString(preTag); + out.writeOptionalString(postTag); + out.writeString(separator); + if (collateQuery != null) { + out.writeBoolean(true); + collateQuery.writeTo(out); + } else { + out.writeBoolean(false); + } + out.writeMap(collateParams); + out.writeOptionalBoolean(collatePrune); + out.writeVInt(this.generators.size()); + for (Entry> entry : this.generators.entrySet()) { + out.writeString(entry.getKey()); + List generatorsList = entry.getValue(); + out.writeVInt(generatorsList.size()); + for (CandidateGenerator generator : generatorsList) { + generator.writeTo(out); + } + } + } + /** * Sets the gram size for the n-gram model used for this suggester. The * default value is 1 corresponding to unigrams. Use @@ -422,8 +490,7 @@ public class PhraseSuggestionBuilder extends SuggestionBuilder> entry : this.generators.entrySet()) { - out.writeString(entry.getKey()); - List generatorsList = entry.getValue(); - out.writeVInt(generatorsList.size()); - for (CandidateGenerator generator : generatorsList) { - generator.writeTo(out); - } - } - } - - @Override - public PhraseSuggestionBuilder doReadFrom(StreamInput in, String field) throws IOException { - PhraseSuggestionBuilder builder = new PhraseSuggestionBuilder(field); - builder.maxErrors = in.readFloat(); - builder.realWordErrorLikelihood = in.readFloat(); - builder.confidence = in.readFloat(); - builder.gramSize = in.readOptionalVInt(); - if (in.readBoolean()) { - builder.model = in.readPhraseSuggestionSmoothingModel(); - } - builder.forceUnigrams = in.readBoolean(); - builder.tokenLimit = in.readVInt(); - builder.preTag = in.readOptionalString(); - builder.postTag = in.readOptionalString(); - builder.separator = in.readString(); - if (in.readBoolean()) { - builder.collateQuery = Template.readTemplate(in); - } - builder.collateParams = in.readMap(); - builder.collatePrune = in.readOptionalBoolean(); - int generatorsEntries = in.readVInt(); - for (int i = 0; i < generatorsEntries; i++) { - String type = in.readString(); - int numberOfGenerators = in.readVInt(); - List generatorsList = new ArrayList<>(numberOfGenerators); - for (int g = 0; g < numberOfGenerators; g++) { - DirectCandidateGeneratorBuilder generator = DirectCandidateGeneratorBuilder.PROTOTYPE.readFrom(in); - generatorsList.add(generator); - } - builder.generators.put(type, generatorsList); - } - return builder; - } - @Override protected boolean doEquals(PhraseSuggestionBuilder other) { return Objects.equals(maxErrors, other.maxErrors) && @@ -723,8 +717,6 @@ public class PhraseSuggestionBuilder extends SuggestionBuilder, ToXContent { String getType(); - CandidateGenerator fromXContent(QueryParseContext parseContext) throws IOException; - PhraseSuggestionContext.DirectCandidateGenerator build(MapperService mapperService) throws IOException; } } diff --git a/core/src/main/java/org/elasticsearch/search/suggest/phrase/PhraseSuggestionContext.java b/core/src/main/java/org/elasticsearch/search/suggest/phrase/PhraseSuggestionContext.java index 80ac850a38..e2d7ff1c41 100644 --- a/core/src/main/java/org/elasticsearch/search/suggest/phrase/PhraseSuggestionContext.java +++ b/core/src/main/java/org/elasticsearch/search/suggest/phrase/PhraseSuggestionContext.java @@ -19,6 +19,8 @@ package org.elasticsearch.search.suggest.phrase; import org.apache.lucene.analysis.Analyzer; +import org.apache.lucene.index.IndexReader; +import org.apache.lucene.index.Terms; import org.apache.lucene.util.BytesRef; import org.elasticsearch.index.query.QueryShardContext; import org.elasticsearch.script.CompiledScript; @@ -38,6 +40,8 @@ class PhraseSuggestionContext extends SuggestionContext { static final float DEFAULT_RWE_ERRORLIKELIHOOD = 0.95f; static final float DEFAULT_MAX_ERRORS = 0.5f; static final String DEFAULT_SEPARATOR = " "; + static final WordScorer.WordScorerFactory DEFAULT_SCORER = (IndexReader reader, Terms terms, String field, double realWordLikelyhood, + BytesRef separator) -> new StupidBackoffScorer(reader, terms, field, realWordLikelyhood, separator, 0.4f); private float maxErrors = DEFAULT_MAX_ERRORS; private BytesRef separator = new BytesRef(DEFAULT_SEPARATOR); @@ -52,10 +56,10 @@ class PhraseSuggestionContext extends SuggestionContext { private boolean prune = DEFAULT_COLLATE_PRUNE; private List generators = new ArrayList<>(); private Map collateScriptParams = new HashMap<>(1); - private WordScorer.WordScorerFactory scorer; + private WordScorer.WordScorerFactory scorer = DEFAULT_SCORER; public PhraseSuggestionContext(QueryShardContext shardContext) { - super(PhraseSuggester.PROTOTYPE, shardContext); + super(PhraseSuggester.INSTANCE, shardContext); } public float maxErrors() { diff --git a/core/src/main/java/org/elasticsearch/search/suggest/phrase/SmoothingModel.java b/core/src/main/java/org/elasticsearch/search/suggest/phrase/SmoothingModel.java index 0163c560de..d2b5b30dc5 100644 --- a/core/src/main/java/org/elasticsearch/search/suggest/phrase/SmoothingModel.java +++ b/core/src/main/java/org/elasticsearch/search/suggest/phrase/SmoothingModel.java @@ -76,11 +76,11 @@ public abstract class SmoothingModel implements NamedWriteable, fieldName = parser.currentName(); } else if (token == XContentParser.Token.START_OBJECT) { if (parseFieldMatcher.match(fieldName, LinearInterpolation.PARSE_FIELD)) { - model = LinearInterpolation.PROTOTYPE.innerFromXContent(parseContext); + model = LinearInterpolation.innerFromXContent(parseContext); } else if (parseFieldMatcher.match(fieldName, Laplace.PARSE_FIELD)) { - model = Laplace.PROTOTYPE.innerFromXContent(parseContext); + model = Laplace.innerFromXContent(parseContext); } else if (parseFieldMatcher.match(fieldName, StupidBackoff.PARSE_FIELD)) { - model = StupidBackoff.PROTOTYPE.innerFromXContent(parseContext); + model = StupidBackoff.innerFromXContent(parseContext); } else { throw new IllegalArgumentException("suggester[phrase] doesn't support object field [" + fieldName + "]"); } @@ -92,8 +92,6 @@ public abstract class SmoothingModel implements NamedWriteable, return model; } - public abstract SmoothingModel innerFromXContent(QueryParseContext parseContext) throws IOException; - public abstract WordScorerFactory buildWordScorerFactory(); /** diff --git a/core/src/main/java/org/elasticsearch/search/suggest/phrase/StupidBackoff.java b/core/src/main/java/org/elasticsearch/search/suggest/phrase/StupidBackoff.java index 951f7f917f..cf1c436640 100644 --- a/core/src/main/java/org/elasticsearch/search/suggest/phrase/StupidBackoff.java +++ b/core/src/main/java/org/elasticsearch/search/suggest/phrase/StupidBackoff.java @@ -49,12 +49,12 @@ public final class StupidBackoff extends SmoothingModel { * Default discount parameter for {@link StupidBackoff} smoothing */ public static final double DEFAULT_BACKOFF_DISCOUNT = 0.4; - public static final StupidBackoff PROTOTYPE = new StupidBackoff(DEFAULT_BACKOFF_DISCOUNT); - private double discount = DEFAULT_BACKOFF_DISCOUNT; - private static final String NAME = "stupid_backoff"; + public static final String NAME = "stupid_backoff"; private static final ParseField DISCOUNT_FIELD = new ParseField("discount"); static final ParseField PARSE_FIELD = new ParseField(NAME); + private double discount = DEFAULT_BACKOFF_DISCOUNT; + /** * Creates a Stupid-Backoff smoothing model. * @@ -65,6 +65,18 @@ public final class StupidBackoff extends SmoothingModel { this.discount = discount; } + /** + * Read from a stream. + */ + public StupidBackoff(StreamInput in) throws IOException { + discount = in.readDouble(); + } + + @Override + public void writeTo(StreamOutput out) throws IOException { + out.writeDouble(discount); + } + /** * @return the discount parameter of the model */ @@ -83,16 +95,6 @@ public final class StupidBackoff extends SmoothingModel { return NAME; } - @Override - public void writeTo(StreamOutput out) throws IOException { - out.writeDouble(discount); - } - - @Override - public StupidBackoff readFrom(StreamInput in) throws IOException { - return new StupidBackoff(in.readDouble()); - } - @Override protected boolean doEquals(SmoothingModel other) { StupidBackoff otherModel = (StupidBackoff) other; @@ -104,8 +106,7 @@ public final class StupidBackoff extends SmoothingModel { return Objects.hash(discount); } - @Override - public SmoothingModel innerFromXContent(QueryParseContext parseContext) throws IOException { + public static SmoothingModel innerFromXContent(QueryParseContext parseContext) throws IOException { XContentParser parser = parseContext.parser(); XContentParser.Token token; String fieldName = null; diff --git a/core/src/main/java/org/elasticsearch/search/suggest/phrase/StupidBackoffScorer.java b/core/src/main/java/org/elasticsearch/search/suggest/phrase/StupidBackoffScorer.java index 5bd3d942b1..ed0573bf00 100644 --- a/core/src/main/java/org/elasticsearch/search/suggest/phrase/StupidBackoffScorer.java +++ b/core/src/main/java/org/elasticsearch/search/suggest/phrase/StupidBackoffScorer.java @@ -26,14 +26,7 @@ import org.elasticsearch.search.suggest.phrase.DirectCandidateGenerator.Candidat import java.io.IOException; -public class StupidBackoffScorer extends WordScorer { - public static final WordScorerFactory FACTORY = new WordScorer.WordScorerFactory() { - @Override - public WordScorer newScorer(IndexReader reader, Terms terms, String field, double realWordLikelyhood, BytesRef separator) throws IOException { - return new StupidBackoffScorer(reader, terms, field, realWordLikelyhood, separator, 0.4f); - } - }; - +class StupidBackoffScorer extends WordScorer { private final double discount; public StupidBackoffScorer(IndexReader reader, Terms terms,String field, double realWordLikelyhood, BytesRef separator, double discount) diff --git a/core/src/main/java/org/elasticsearch/search/suggest/term/TermSuggester.java b/core/src/main/java/org/elasticsearch/search/suggest/term/TermSuggester.java index 4bffb2dfe8..a06baccb99 100644 --- a/core/src/main/java/org/elasticsearch/search/suggest/term/TermSuggester.java +++ b/core/src/main/java/org/elasticsearch/search/suggest/term/TermSuggester.java @@ -27,7 +27,9 @@ import org.apache.lucene.util.BytesRef; import org.apache.lucene.util.BytesRefBuilder; import org.apache.lucene.util.CharsRefBuilder; import org.elasticsearch.common.bytes.BytesArray; +import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.text.Text; +import org.elasticsearch.index.query.QueryParseContext; import org.elasticsearch.search.suggest.SuggestUtils; import org.elasticsearch.search.suggest.Suggester; import org.elasticsearch.search.suggest.SuggestionBuilder; @@ -39,7 +41,9 @@ import java.util.List; public final class TermSuggester extends Suggester { - public static final TermSuggester PROTOTYPE = new TermSuggester(); + public static final TermSuggester INSTANCE = new TermSuggester(); + + private TermSuggester() {} @Override public TermSuggestion innerExecute(String name, TermSuggestionContext suggestion, IndexSearcher searcher, CharsRefBuilder spare) @@ -79,6 +83,16 @@ public final class TermSuggester extends Suggester { return result; } + @Override + public SuggestionBuilder innerFromXContent(QueryParseContext context) throws IOException { + return TermSuggestionBuilder.innerFromXContent(context); + } + + @Override + public SuggestionBuilder read(StreamInput in) throws IOException { + return new TermSuggestionBuilder(in); + } + private static class Token { public final Term term; @@ -92,10 +106,4 @@ public final class TermSuggester extends Suggester { } } - - @Override - public SuggestionBuilder getBuilderPrototype() { - return TermSuggestionBuilder.PROTOTYPE; - } - } diff --git a/core/src/main/java/org/elasticsearch/search/suggest/term/TermSuggestion.java b/core/src/main/java/org/elasticsearch/search/suggest/term/TermSuggestion.java index bc4006469a..dc29b6a148 100644 --- a/core/src/main/java/org/elasticsearch/search/suggest/term/TermSuggestion.java +++ b/core/src/main/java/org/elasticsearch/search/suggest/term/TermSuggestion.java @@ -111,7 +111,7 @@ public class TermSuggestion extends Suggestion { @Override protected void innerReadFrom(StreamInput in) throws IOException { super.innerReadFrom(in); - sort = SortBy.PROTOTYPE.readFrom(in); + sort = SortBy.readFromStream(in); } @Override diff --git a/core/src/main/java/org/elasticsearch/search/suggest/term/TermSuggestionBuilder.java b/core/src/main/java/org/elasticsearch/search/suggest/term/TermSuggestionBuilder.java index 0cb9d1604a..0676bbf859 100644 --- a/core/src/main/java/org/elasticsearch/search/suggest/term/TermSuggestionBuilder.java +++ b/core/src/main/java/org/elasticsearch/search/suggest/term/TermSuggestionBuilder.java @@ -69,8 +69,6 @@ import static org.elasticsearch.search.suggest.SuggestUtils.Fields.SUGGEST_MODE; * global options, but are only applicable for this suggestion. */ public class TermSuggestionBuilder extends SuggestionBuilder { - - public static final TermSuggestionBuilder PROTOTYPE = new TermSuggestionBuilder("_na_"); private static final String SUGGESTION_NAME = "term"; private SuggestMode suggestMode = SuggestMode.MISSING; @@ -105,6 +103,37 @@ public class TermSuggestionBuilder extends SuggestionBuilder= values().length) { throw new IOException("Unknown SuggestMode ordinal [" + ordinal + "]"); @@ -579,15 +574,12 @@ public class TermSuggestionBuilder extends SuggestionBuilder= values().length) { throw new IOException("Unknown StringDistanceImpl ordinal [" + ordinal + "]"); diff --git a/core/src/main/java/org/elasticsearch/search/suggest/term/TermSuggestionContext.java b/core/src/main/java/org/elasticsearch/search/suggest/term/TermSuggestionContext.java index 5102ef9901..c950e5729d 100644 --- a/core/src/main/java/org/elasticsearch/search/suggest/term/TermSuggestionContext.java +++ b/core/src/main/java/org/elasticsearch/search/suggest/term/TermSuggestionContext.java @@ -27,7 +27,7 @@ final class TermSuggestionContext extends SuggestionContext { private final DirectSpellcheckerSettings settings = new DirectSpellcheckerSettings(); public TermSuggestionContext(QueryShardContext shardContext) { - super(TermSuggester.PROTOTYPE, shardContext); + super(TermSuggester.INSTANCE, shardContext); } public DirectSpellcheckerSettings getDirectSpellCheckerSettings() { -- cgit v1.2.3