Remove PROTOTYPEs from suggesters
Also stops using guice for suggesters at all and lots of checkstyle.
This commit is contained in:
parent
101a32573c
commit
df08854c60
|
@ -860,19 +860,14 @@
|
|||
<suppress files="core[/\\]src[/\\]main[/\\]java[/\\]org[/\\]elasticsearch[/\\]search[/\\]suggest[/\\]SuggestBuilder.java" checks="LineLength" />
|
||||
<suppress files="core[/\\]src[/\\]main[/\\]java[/\\]org[/\\]elasticsearch[/\\]search[/\\]suggest[/\\]SuggestContextParser.java" checks="LineLength" />
|
||||
<suppress files="core[/\\]src[/\\]main[/\\]java[/\\]org[/\\]elasticsearch[/\\]search[/\\]suggest[/\\]SuggestUtils.java" checks="LineLength" />
|
||||
<suppress files="core[/\\]src[/\\]main[/\\]java[/\\]org[/\\]elasticsearch[/\\]search[/\\]suggest[/\\]Suggesters.java" checks="LineLength" />
|
||||
<suppress files="core[/\\]src[/\\]main[/\\]java[/\\]org[/\\]elasticsearch[/\\]search[/\\]suggest[/\\]completion[/\\]CompletionSuggestParser.java" checks="LineLength" />
|
||||
<suppress files="core[/\\]src[/\\]main[/\\]java[/\\]org[/\\]elasticsearch[/\\]search[/\\]suggest[/\\]completion[/\\]context[/\\]CategoryContextMapping.java" checks="LineLength" />
|
||||
<suppress files="core[/\\]src[/\\]main[/\\]java[/\\]org[/\\]elasticsearch[/\\]search[/\\]suggest[/\\]completion[/\\]context[/\\]ContextMapping.java" checks="LineLength" />
|
||||
<suppress files="core[/\\]src[/\\]main[/\\]java[/\\]org[/\\]elasticsearch[/\\]search[/\\]suggest[/\\]completion[/\\]context[/\\]GeoContextMapping.java" checks="LineLength" />
|
||||
<suppress files="core[/\\]src[/\\]main[/\\]java[/\\]org[/\\]elasticsearch[/\\]search[/\\]suggest[/\\]completion[/\\]context[/\\]GeoQueryContext.java" checks="LineLength" />
|
||||
<suppress files="core[/\\]src[/\\]main[/\\]java[/\\]org[/\\]elasticsearch[/\\]search[/\\]suggest[/\\]phrase[/\\]CandidateScorer.java" checks="LineLength" />
|
||||
<suppress files="core[/\\]src[/\\]main[/\\]java[/\\]org[/\\]elasticsearch[/\\]search[/\\]suggest[/\\]phrase[/\\]DirectCandidateGenerator.java" checks="LineLength" />
|
||||
<suppress files="core[/\\]src[/\\]main[/\\]java[/\\]org[/\\]elasticsearch[/\\]search[/\\]suggest[/\\]phrase[/\\]LaplaceScorer.java" checks="LineLength" />
|
||||
<suppress files="core[/\\]src[/\\]main[/\\]java[/\\]org[/\\]elasticsearch[/\\]search[/\\]suggest[/\\]phrase[/\\]LinearInterpoatingScorer.java" checks="LineLength" />
|
||||
<suppress files="core[/\\]src[/\\]main[/\\]java[/\\]org[/\\]elasticsearch[/\\]search[/\\]suggest[/\\]phrase[/\\]NoisyChannelSpellChecker.java" checks="LineLength" />
|
||||
<suppress files="core[/\\]src[/\\]main[/\\]java[/\\]org[/\\]elasticsearch[/\\]search[/\\]suggest[/\\]phrase[/\\]PhraseSuggestParser.java" checks="LineLength" />
|
||||
<suppress files="core[/\\]src[/\\]main[/\\]java[/\\]org[/\\]elasticsearch[/\\]search[/\\]suggest[/\\]phrase[/\\]StupidBackoffScorer.java" checks="LineLength" />
|
||||
<suppress files="core[/\\]src[/\\]main[/\\]java[/\\]org[/\\]elasticsearch[/\\]search[/\\]suggest[/\\]phrase[/\\]WordScorer.java" checks="LineLength" />
|
||||
<suppress files="core[/\\]src[/\\]main[/\\]java[/\\]org[/\\]elasticsearch[/\\]search[/\\]suggest[/\\]term[/\\]TermSuggestParser.java" checks="LineLength" />
|
||||
<suppress files="core[/\\]src[/\\]main[/\\]java[/\\]org[/\\]elasticsearch[/\\]snapshots[/\\]RestoreService.java" checks="LineLength" />
|
||||
|
@ -1377,7 +1372,6 @@
|
|||
<suppress files="core[/\\]src[/\\]test[/\\]java[/\\]org[/\\]elasticsearch[/\\]search[/\\]suggest[/\\]CustomSuggester.java" checks="LineLength" />
|
||||
<suppress files="core[/\\]src[/\\]test[/\\]java[/\\]org[/\\]elasticsearch[/\\]search[/\\]suggest[/\\]completion[/\\]CategoryContextMappingTests.java" checks="LineLength" />
|
||||
<suppress files="core[/\\]src[/\\]test[/\\]java[/\\]org[/\\]elasticsearch[/\\]search[/\\]suggest[/\\]completion[/\\]GeoContextMappingTests.java" checks="LineLength" />
|
||||
<suppress files="core[/\\]src[/\\]test[/\\]java[/\\]org[/\\]elasticsearch[/\\]search[/\\]suggest[/\\]phrase[/\\]DirectCandidateGeneratorTests.java" checks="LineLength" />
|
||||
<suppress files="core[/\\]src[/\\]test[/\\]java[/\\]org[/\\]elasticsearch[/\\]search[/\\]suggest[/\\]phrase[/\\]NoisyChannelSpellCheckerTests.java" checks="LineLength" />
|
||||
<suppress files="core[/\\]src[/\\]test[/\\]java[/\\]org[/\\]elasticsearch[/\\]similarity[/\\]SimilarityIT.java" checks="LineLength" />
|
||||
<suppress files="core[/\\]src[/\\]test[/\\]java[/\\]org[/\\]elasticsearch[/\\]snapshots[/\\]AbstractSnapshotIntegTestCase.java" checks="LineLength" />
|
||||
|
|
|
@ -115,6 +115,19 @@ public abstract class StreamInput extends InputStream {
|
|||
return readBytesReference(length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads an optional bytes reference from this stream. It might hold an actual reference to the underlying bytes of the stream. Use this
|
||||
* only if you must differentiate null from empty. Use {@link StreamInput#readBytesReference()} and
|
||||
* {@link StreamOutput#writeBytesReference(BytesReference)} if you do not.
|
||||
*/
|
||||
public BytesReference readOptionalBytesReference() throws IOException {
|
||||
int length = readVInt() - 1;
|
||||
if (length < 0) {
|
||||
return null;
|
||||
}
|
||||
return readBytesReference(length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a bytes reference from this stream, might hold an actual reference to the underlying
|
||||
* bytes of the stream.
|
||||
|
|
|
@ -146,6 +146,19 @@ public abstract class StreamOutput extends OutputStream {
|
|||
bytes.writeTo(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes an optional bytes reference including a length header. Use this if you need to differentiate between null and empty bytes
|
||||
* references. Use {@link #writeBytesReference(BytesReference)} and {@link StreamInput#readBytesReference()} if you do not.
|
||||
*/
|
||||
public void writeOptionalBytesReference(@Nullable BytesReference bytes) throws IOException {
|
||||
if (bytes == null) {
|
||||
writeVInt(0);
|
||||
return;
|
||||
}
|
||||
writeVInt(bytes.length() + 1);
|
||||
bytes.writeTo(this);
|
||||
}
|
||||
|
||||
public void writeBytesRef(BytesRef bytes) throws IOException {
|
||||
if (bytes == null) {
|
||||
writeVInt(0);
|
||||
|
|
|
@ -46,7 +46,8 @@ public interface Writeable<T> extends StreamableReader<T> { // TODO remove exten
|
|||
@Override
|
||||
default T readFrom(StreamInput in) throws IOException {
|
||||
// See class javadoc for reasoning
|
||||
throw new UnsupportedOperationException("Prefer calling a constructor that takes a StreamInput to calling readFrom.");
|
||||
throw new UnsupportedOperationException(
|
||||
"Prefer calling a constructor or static method that takes a StreamInput to calling readFrom.");
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -56,6 +57,9 @@ public interface Writeable<T> extends StreamableReader<T> { // TODO remove exten
|
|||
*/
|
||||
@FunctionalInterface
|
||||
interface Reader<R> {
|
||||
R read(StreamInput t) throws IOException;
|
||||
/**
|
||||
* Read R from a stream.
|
||||
*/
|
||||
R read(StreamInput in) throws IOException;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -249,7 +249,7 @@ public class SearchModule extends AbstractModule {
|
|||
private final Set<Aggregator.Parser> aggParsers = new HashSet<>();
|
||||
private final Set<PipelineAggregator.Parser> 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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,15 +36,12 @@ public enum SortBy implements Writeable<SortBy> {
|
|||
/** 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 + "]");
|
||||
|
|
|
@ -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<T extends SuggestionSearchContext.SuggestionContext> {
|
||||
public abstract class Suggester<T extends SuggestionSearchContext.SuggestionContext> implements Writeable.Reader<SuggestionBuilder<?>> {
|
||||
|
||||
protected abstract Suggest.Suggestion<? extends Suggest.Suggestion.Entry<? extends Suggest.Suggestion.Entry.Option>>
|
||||
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<? extends SuggestionBuilder> getBuilderPrototype();
|
||||
public abstract SuggestionBuilder<?> innerFromXContent(QueryParseContext context) throws IOException;
|
||||
|
||||
public Suggest.Suggestion<? extends Suggest.Suggestion.Entry<? extends Suggest.Suggestion.Entry.Option>>
|
||||
execute(String name, T suggestion, IndexSearcher searcher, CharsRefBuilder spare) throws IOException {
|
||||
|
|
|
@ -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<Suggester> {
|
||||
private final Map<String, Suggester> parsers;
|
||||
public final class Suggesters {
|
||||
private final Map<String, Suggester<?>> 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);
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
@Inject
|
||||
public Suggesters(Map<String, Suggester> suggesters) {
|
||||
super("suggester", Suggester.class, new HashSet<>(Arrays.asList("phrase", "term", "completion")), Suggesters.class, SuggestPhase.class);
|
||||
this.parsers = Collections.unmodifiableMap(addBuildIns(suggesters));
|
||||
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);
|
||||
}
|
||||
|
||||
private static Map<String, Suggester> addBuildIns(Map<String, Suggester> suggesters) {
|
||||
final Map<String, Suggester> map = new HashMap<>();
|
||||
map.put("phrase", PhraseSuggester.PROTOTYPE);
|
||||
map.put("term", TermSuggester.PROTOTYPE);
|
||||
map.put("completion", CompletionSuggester.PROTOTYPE);
|
||||
map.putAll(suggesters);
|
||||
return map;
|
||||
}
|
||||
|
||||
public SuggestionBuilder<? extends 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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -86,6 +86,34 @@ public abstract class SuggestionBuilder<T extends SuggestionBuilder<T>> 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<T extends SuggestionBuilder<T>> 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<T extends SuggestionBuilder<T>> extends
|
|||
return suggestionBuilder;
|
||||
}
|
||||
|
||||
protected abstract SuggestionBuilder<T> innerFromXContent(QueryParseContext parseContext) throws IOException;
|
||||
|
||||
protected abstract SuggestionContext build(QueryShardContext context) throws IOException;
|
||||
|
||||
/**
|
||||
|
@ -340,40 +362,6 @@ public abstract class SuggestionBuilder<T extends SuggestionBuilder<T>> 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) {
|
||||
|
|
|
@ -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<CompletionSuggestionContext> {
|
||||
|
||||
public static final CompletionSuggester PROTOTYPE = new CompletionSuggester();
|
||||
public static final CompletionSuggester INSTANCE = new CompletionSuggester();
|
||||
|
||||
private CompletionSuggester() {}
|
||||
|
||||
@Override
|
||||
protected Suggest.Suggestion<? extends Suggest.Suggestion.Entry<? extends Suggest.Suggestion.Entry.Option>> innerExecute(String name,
|
||||
|
@ -267,7 +271,12 @@ public class CompletionSuggester extends Suggester<CompletionSuggestionContext>
|
|||
}
|
||||
|
||||
@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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<CompletionSuggestionBuilder> {
|
||||
|
||||
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<CompletionSug
|
|||
payloadFields = in.payloadFields;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read from a stream.
|
||||
*/
|
||||
public CompletionSuggestionBuilder(StreamInput in) throws IOException {
|
||||
super(in);
|
||||
payloadFields = new ArrayList<>();
|
||||
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<CompletionSug
|
|||
* see {@link org.elasticsearch.search.suggest.completion.context.CategoryQueryContext}
|
||||
* and {@link org.elasticsearch.search.suggest.completion.context.GeoQueryContext}
|
||||
*/
|
||||
public CompletionSuggestionBuilder contexts(Map<String, List<? extends QueryContext>> queryContexts) {
|
||||
public CompletionSuggestionBuilder contexts(Map<String, List<? extends ToXContent>> queryContexts) {
|
||||
Objects.requireNonNull(queryContexts, "contexts must not be null");
|
||||
try {
|
||||
XContentBuilder contentBuilder = XContentFactory.jsonBuilder();
|
||||
contentBuilder.startObject();
|
||||
for (Map.Entry<String, List<? extends QueryContext>> contextEntry : queryContexts.entrySet()) {
|
||||
for (Map.Entry<String, List<? extends ToXContent>> 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<CompletionSug
|
|||
return builder;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected CompletionSuggestionBuilder innerFromXContent(QueryParseContext parseContext) throws IOException {
|
||||
static CompletionSuggestionBuilder innerFromXContent(QueryParseContext parseContext) throws IOException {
|
||||
CompletionSuggestionBuilder.InnerBuilder builder = new CompletionSuggestionBuilder.InnerBuilder();
|
||||
TLP_PARSER.parse(parseContext.parser(), builder);
|
||||
String field = builder.field;
|
||||
|
@ -303,52 +319,6 @@ public class CompletionSuggestionBuilder extends SuggestionBuilder<CompletionSug
|
|||
return SUGGESTION_NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doWriteTo(StreamOutput out) throws IOException {
|
||||
out.writeBoolean(payloadFields.isEmpty() == false);
|
||||
if (payloadFields.isEmpty() == false) {
|
||||
out.writeVInt(payloadFields.size());
|
||||
for (String payloadField : payloadFields) {
|
||||
out.writeString(payloadField);
|
||||
}
|
||||
}
|
||||
out.writeBoolean(fuzzyOptions != null);
|
||||
if (fuzzyOptions != null) {
|
||||
fuzzyOptions.writeTo(out);
|
||||
}
|
||||
out.writeBoolean(regexOptions != null);
|
||||
if (regexOptions != null) {
|
||||
regexOptions.writeTo(out);
|
||||
}
|
||||
out.writeBoolean(contextBytes != null);
|
||||
if (contextBytes != null) {
|
||||
out.writeBytesReference(contextBytes);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletionSuggestionBuilder doReadFrom(StreamInput in, String field) throws IOException {
|
||||
CompletionSuggestionBuilder completionSuggestionBuilder = new CompletionSuggestionBuilder(field);
|
||||
if (in.readBoolean()) {
|
||||
int numPayloadField = in.readVInt();
|
||||
List<String> 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) &&
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -89,7 +89,26 @@ public class FuzzyOptions implements ToXContent, Writeable<FuzzyOptions> {
|
|||
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<FuzzyOptions> {
|
|||
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
|
||||
*/
|
||||
|
|
|
@ -67,14 +67,25 @@ public class RegexOptions implements ToXContent, Writeable<RegexOptions> {
|
|||
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<RegexOptions> {
|
|||
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
|
||||
*/
|
||||
|
|
|
@ -139,8 +139,8 @@ public class CategoryContextMapping extends ContextMapping<CategoryQueryContext>
|
|||
}
|
||||
|
||||
@Override
|
||||
protected CategoryQueryContext prototype() {
|
||||
return CategoryQueryContext.PROTOTYPE;
|
||||
protected CategoryQueryContext fromXContent(XContentParser parser) throws IOException {
|
||||
return CategoryQueryContext.fromXContent(parser);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -40,7 +40,7 @@ import java.util.Set;
|
|||
*
|
||||
* Implementations have to define how contexts are parsed at query/index time
|
||||
*/
|
||||
public abstract class ContextMapping<T extends QueryContext> implements ToXContent {
|
||||
public abstract class ContextMapping<T extends ToXContent> implements ToXContent {
|
||||
|
||||
public static final String FIELD_TYPE = "type";
|
||||
public static final String FIELD_NAME = "name";
|
||||
|
@ -99,7 +99,7 @@ public abstract class ContextMapping<T extends QueryContext> 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<T extends QueryContext> implements ToXConte
|
|||
List<T> 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);
|
||||
|
|
|
@ -223,8 +223,8 @@ public class GeoContextMapping extends ContextMapping<GeoQueryContext> {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected GeoQueryContext prototype() {
|
||||
return GeoQueryContext.PROTOTYPE;
|
||||
protected GeoQueryContext fromXContent(XContentParser parser) throws IOException {
|
||||
return GeoQueryContext.fromXContent(parser);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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<Candidate> candidates) throws IOException {
|
||||
protected void postFilter(final Candidate candidate, final CharsRefBuilder spare, BytesRefBuilder byteSpare,
|
||||
final List<Candidate> 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
|
||||
|
|
|
@ -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<String> tmpFieldName = new HashSet<>(1); // bucket for the field
|
||||
// name, needed as
|
||||
// constructor arg
|
||||
// later
|
||||
PARSER.parse(parseContext.parser(),
|
||||
new Tuple<Set<String>, DirectCandidateGeneratorBuilder>(tmpFieldName, tempGenerator));
|
||||
// bucket for the field name, needed as constructor arg later
|
||||
Set<String> tmpFieldName = new HashSet<>(1);
|
||||
PARSER.parse(parseContext.parser(), new Tuple<Set<String>, 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,
|
||||
|
|
|
@ -44,15 +44,15 @@ import java.util.Objects;
|
|||
* </p>
|
||||
*/
|
||||
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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -45,16 +45,16 @@ import java.util.Objects;
|
|||
* </p>
|
||||
*/
|
||||
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;
|
||||
|
|
|
@ -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<PhraseSuggestionContext> {
|
|||
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<PhraseSuggestionContext> {
|
|||
}
|
||||
|
||||
@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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -60,8 +60,6 @@ public class PhraseSuggestionBuilder extends SuggestionBuilder<PhraseSuggestionB
|
|||
|
||||
private static final String SUGGESTION_NAME = "phrase";
|
||||
|
||||
public static final PhraseSuggestionBuilder PROTOTYPE = new PhraseSuggestionBuilder("_na_");
|
||||
|
||||
protected static final ParseField MAXERRORS_FIELD = new ParseField("max_errors");
|
||||
protected static final ParseField RWE_LIKELIHOOD_FIELD = new ParseField("real_word_error_likelihood");
|
||||
protected static final ParseField SEPARATOR_FIELD = new ParseField("separator");
|
||||
|
@ -121,6 +119,76 @@ public class PhraseSuggestionBuilder extends SuggestionBuilder<PhraseSuggestionB
|
|||
generators.putAll(in.generators);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read from a stream.
|
||||
*/
|
||||
PhraseSuggestionBuilder(StreamInput in) throws IOException {
|
||||
super(in);
|
||||
maxErrors = in.readFloat();
|
||||
realWordErrorLikelihood = in.readFloat();
|
||||
confidence = in.readFloat();
|
||||
gramSize = in.readOptionalVInt();
|
||||
if (in.readBoolean()) {
|
||||
model = in.readPhraseSuggestionSmoothingModel();
|
||||
}
|
||||
forceUnigrams = in.readBoolean();
|
||||
tokenLimit = in.readVInt();
|
||||
preTag = in.readOptionalString();
|
||||
postTag = in.readOptionalString();
|
||||
separator = in.readString();
|
||||
if (in.readBoolean()) {
|
||||
collateQuery = Template.readTemplate(in);
|
||||
}
|
||||
collateParams = in.readMap();
|
||||
collatePrune = in.readOptionalBoolean();
|
||||
int generatorsEntries = in.readVInt();
|
||||
for (int i = 0; i < generatorsEntries; i++) {
|
||||
String type = in.readString();
|
||||
int numberOfGenerators = in.readVInt();
|
||||
List<CandidateGenerator> 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<String, List<CandidateGenerator>> entry : this.generators.entrySet()) {
|
||||
out.writeString(entry.getKey());
|
||||
List<CandidateGenerator> 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 <tt>1</tt> corresponding to <tt>unigrams</tt>. Use
|
||||
|
@ -422,8 +490,7 @@ public class PhraseSuggestionBuilder extends SuggestionBuilder<PhraseSuggestionB
|
|||
return builder;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PhraseSuggestionBuilder innerFromXContent(QueryParseContext parseContext) throws IOException {
|
||||
static PhraseSuggestionBuilder innerFromXContent(QueryParseContext parseContext) throws IOException {
|
||||
XContentParser parser = parseContext.parser();
|
||||
PhraseSuggestionBuilder tmpSuggestion = new PhraseSuggestionBuilder("_na_");
|
||||
ParseFieldMatcher parseFieldMatcher = parseContext.parseFieldMatcher();
|
||||
|
@ -464,7 +531,7 @@ public class PhraseSuggestionBuilder extends SuggestionBuilder<PhraseSuggestionB
|
|||
if (parseFieldMatcher.match(currentFieldName, DirectCandidateGeneratorBuilder.DIRECT_GENERATOR_FIELD)) {
|
||||
// for now we only have a single type of generators
|
||||
while ((token = parser.nextToken()) == Token.START_OBJECT) {
|
||||
tmpSuggestion.addCandidateGenerator(DirectCandidateGeneratorBuilder.PROTOTYPE.fromXContent(parseContext));
|
||||
tmpSuggestion.addCandidateGenerator(DirectCandidateGeneratorBuilder.fromXContent(parseContext));
|
||||
}
|
||||
} else {
|
||||
throw new ParsingException(parser.getTokenLocation(),
|
||||
|
@ -578,10 +645,6 @@ public class PhraseSuggestionBuilder extends SuggestionBuilder<PhraseSuggestionB
|
|||
suggestionContext.setCollatePrune(this.collatePrune);
|
||||
}
|
||||
|
||||
if (suggestionContext.model() == null) {
|
||||
suggestionContext.setModel(StupidBackoffScorer.FACTORY);
|
||||
}
|
||||
|
||||
if (this.gramSize == null || suggestionContext.generators().isEmpty()) {
|
||||
final ShingleTokenFilterFactory.Factory shingleFilterFactory = SuggestUtils
|
||||
.getShingleFilterFactory(suggestionContext.getAnalyzer());
|
||||
|
@ -623,75 +686,6 @@ public class PhraseSuggestionBuilder extends SuggestionBuilder<PhraseSuggestionB
|
|||
return SUGGESTION_NAME;
|
||||
}
|
||||
|
||||
@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<String, List<CandidateGenerator>> entry : this.generators.entrySet()) {
|
||||
out.writeString(entry.getKey());
|
||||
List<CandidateGenerator> 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<CandidateGenerator> 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<PhraseSuggestionB
|
|||
public interface CandidateGenerator extends Writeable<CandidateGenerator>, ToXContent {
|
||||
String getType();
|
||||
|
||||
CandidateGenerator fromXContent(QueryParseContext parseContext) throws IOException;
|
||||
|
||||
PhraseSuggestionContext.DirectCandidateGenerator build(MapperService mapperService) throws IOException;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<DirectCandidateGenerator> generators = new ArrayList<>();
|
||||
private Map<String, Object> 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() {
|
||||
|
|
|
@ -76,11 +76,11 @@ public abstract class SmoothingModel implements NamedWriteable<SmoothingModel>,
|
|||
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<SmoothingModel>,
|
|||
return model;
|
||||
}
|
||||
|
||||
public abstract SmoothingModel innerFromXContent(QueryParseContext parseContext) throws IOException;
|
||||
|
||||
public abstract WordScorerFactory buildWordScorerFactory();
|
||||
|
||||
/**
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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<TermSuggestionContext> {
|
||||
|
||||
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<TermSuggestionContext> {
|
|||
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<TermSuggestionContext> {
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public SuggestionBuilder<?> getBuilderPrototype() {
|
||||
return TermSuggestionBuilder.PROTOTYPE;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -111,7 +111,7 @@ public class TermSuggestion extends Suggestion<TermSuggestion.Entry> {
|
|||
@Override
|
||||
protected void innerReadFrom(StreamInput in) throws IOException {
|
||||
super.innerReadFrom(in);
|
||||
sort = SortBy.PROTOTYPE.readFrom(in);
|
||||
sort = SortBy.readFromStream(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -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<TermSuggestionBuilder> {
|
||||
|
||||
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<TermSuggestionBuild
|
|||
minDocFreq = in.minDocFreq;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read from a stream.
|
||||
*/
|
||||
TermSuggestionBuilder(StreamInput in) throws IOException {
|
||||
super(in);
|
||||
suggestMode = SuggestMode.readFromStream(in);
|
||||
accuracy = in.readFloat();
|
||||
sort = SortBy.readFromStream(in);
|
||||
stringDistance = StringDistanceImpl.readFromStream(in);
|
||||
maxEdits = in.readVInt();
|
||||
maxInspections = in.readVInt();
|
||||
maxTermFreq = in.readFloat();
|
||||
prefixLength = in.readVInt();
|
||||
minWordLength = in.readVInt();
|
||||
minDocFreq = in.readFloat();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doWriteTo(StreamOutput out) throws IOException {
|
||||
suggestMode.writeTo(out);
|
||||
out.writeFloat(accuracy);
|
||||
sort.writeTo(out);
|
||||
stringDistance.writeTo(out);
|
||||
out.writeVInt(maxEdits);
|
||||
out.writeVInt(maxInspections);
|
||||
out.writeFloat(maxTermFreq);
|
||||
out.writeVInt(prefixLength);
|
||||
out.writeVInt(minWordLength);
|
||||
out.writeFloat(minDocFreq);
|
||||
}
|
||||
|
||||
/**
|
||||
* The global suggest mode controls what suggested terms are included or
|
||||
* controls for what suggest text tokens, terms should be suggested for.
|
||||
|
@ -360,8 +389,7 @@ public class TermSuggestionBuilder extends SuggestionBuilder<TermSuggestionBuild
|
|||
return builder;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected TermSuggestionBuilder innerFromXContent(QueryParseContext parseContext) throws IOException {
|
||||
static TermSuggestionBuilder innerFromXContent(QueryParseContext parseContext) throws IOException {
|
||||
XContentParser parser = parseContext.parser();
|
||||
TermSuggestionBuilder tmpSuggestion = new TermSuggestionBuilder("_na_");
|
||||
ParseFieldMatcher parseFieldMatcher = parseContext.parseFieldMatcher();
|
||||
|
@ -442,36 +470,6 @@ public class TermSuggestionBuilder extends SuggestionBuilder<TermSuggestionBuild
|
|||
return SUGGESTION_NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doWriteTo(StreamOutput out) throws IOException {
|
||||
suggestMode.writeTo(out);
|
||||
out.writeFloat(accuracy);
|
||||
sort.writeTo(out);
|
||||
stringDistance.writeTo(out);
|
||||
out.writeVInt(maxEdits);
|
||||
out.writeVInt(maxInspections);
|
||||
out.writeFloat(maxTermFreq);
|
||||
out.writeVInt(prefixLength);
|
||||
out.writeVInt(minWordLength);
|
||||
out.writeFloat(minDocFreq);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TermSuggestionBuilder doReadFrom(StreamInput in, String field) throws IOException {
|
||||
TermSuggestionBuilder builder = new TermSuggestionBuilder(field);
|
||||
builder.suggestMode = SuggestMode.PROTOTYPE.readFrom(in);
|
||||
builder.accuracy = in.readFloat();
|
||||
builder.sort = SortBy.PROTOTYPE.readFrom(in);
|
||||
builder.stringDistance = StringDistanceImpl.PROTOTYPE.readFrom(in);
|
||||
builder.maxEdits = in.readVInt();
|
||||
builder.maxInspections = in.readVInt();
|
||||
builder.maxTermFreq = in.readFloat();
|
||||
builder.prefixLength = in.readVInt();
|
||||
builder.minWordLength = in.readVInt();
|
||||
builder.minDocFreq = in.readFloat();
|
||||
return builder;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean doEquals(TermSuggestionBuilder other) {
|
||||
return Objects.equals(suggestMode, other.suggestMode) &&
|
||||
|
@ -516,15 +514,12 @@ public class TermSuggestionBuilder extends SuggestionBuilder<TermSuggestionBuild
|
|||
}
|
||||
};
|
||||
|
||||
protected static SuggestMode PROTOTYPE = MISSING;
|
||||
|
||||
@Override
|
||||
public void writeTo(final StreamOutput out) throws IOException {
|
||||
out.writeVInt(ordinal());
|
||||
}
|
||||
|
||||
@Override
|
||||
public SuggestMode readFrom(final StreamInput in) throws IOException {
|
||||
public static SuggestMode readFromStream(final StreamInput in) throws IOException {
|
||||
int ordinal = in.readVInt();
|
||||
if (ordinal < 0 || ordinal >= values().length) {
|
||||
throw new IOException("Unknown SuggestMode ordinal [" + ordinal + "]");
|
||||
|
@ -579,15 +574,12 @@ public class TermSuggestionBuilder extends SuggestionBuilder<TermSuggestionBuild
|
|||
}
|
||||
};
|
||||
|
||||
protected static StringDistanceImpl PROTOTYPE = INTERNAL;
|
||||
|
||||
@Override
|
||||
public void writeTo(final StreamOutput out) throws IOException {
|
||||
out.writeVInt(ordinal());
|
||||
}
|
||||
|
||||
@Override
|
||||
public StringDistanceImpl readFrom(final StreamInput in) throws IOException {
|
||||
public static StringDistanceImpl readFromStream(final StreamInput in) throws IOException {
|
||||
int ordinal = in.readVInt();
|
||||
if (ordinal < 0 || ordinal >= values().length) {
|
||||
throw new IOException("Unknown StringDistanceImpl ordinal [" + ordinal + "]");
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -29,6 +29,11 @@ import static org.hamcrest.Matchers.equalTo;
|
|||
* Abstract class offering base functionality for testing @{link Writeable} enums.
|
||||
*/
|
||||
public abstract class AbstractWriteableEnumTestCase extends ESTestCase {
|
||||
private final Writeable.Reader<?> reader;
|
||||
|
||||
public AbstractWriteableEnumTestCase(Writeable.Reader<?> reader) {
|
||||
this.reader = reader;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that the ordinals for the enum are consistent (i.e. the order hasn't changed)
|
||||
|
@ -52,7 +57,7 @@ public abstract class AbstractWriteableEnumTestCase extends ESTestCase {
|
|||
public abstract void testWriteTo() throws IOException;
|
||||
|
||||
// a convenience method for testing the write of a writeable enum
|
||||
protected static void assertWriteToStream(final Writeable writeableEnum, final int ordinal) throws IOException {
|
||||
protected static <T> void assertWriteToStream(final Writeable<T> writeableEnum, final int ordinal) throws IOException {
|
||||
try (BytesStreamOutput out = new BytesStreamOutput()) {
|
||||
writeableEnum.writeTo(out);
|
||||
try (StreamInput in = StreamInput.wrap(out.bytes())) {
|
||||
|
@ -62,13 +67,12 @@ public abstract class AbstractWriteableEnumTestCase extends ESTestCase {
|
|||
}
|
||||
|
||||
// a convenience method for testing the read of a writeable enum
|
||||
protected static <T extends Writeable<T>> void assertReadFromStream(final int ordinal, final Writeable<T> expected) throws IOException {
|
||||
protected <T extends Writeable<T>> void assertReadFromStream(final int ordinal, final Writeable<T> expected) throws IOException {
|
||||
try (BytesStreamOutput out = new BytesStreamOutput()) {
|
||||
out.writeVInt(ordinal);
|
||||
try (StreamInput in = StreamInput.wrap(out.bytes())) {
|
||||
assertThat(expected.readFrom(in), equalTo(expected));
|
||||
assertThat(reader.read(in), equalTo(expected));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -20,12 +20,14 @@
|
|||
package org.elasticsearch.common.io.stream;
|
||||
|
||||
import org.apache.lucene.util.Constants;
|
||||
import org.elasticsearch.common.bytes.BytesArray;
|
||||
import org.elasticsearch.common.geo.GeoPoint;
|
||||
import org.elasticsearch.common.lucene.BytesRefs;
|
||||
import org.elasticsearch.common.util.BigArrays;
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Objects;
|
||||
|
||||
import static org.hamcrest.Matchers.closeTo;
|
||||
|
@ -275,6 +277,9 @@ public class BytesStreamsTests extends ESTestCase {
|
|||
out.writeString("hello");
|
||||
out.writeString("goodbye");
|
||||
out.writeGenericValue(BytesRefs.toBytesRef("bytesref"));
|
||||
out.writeStringArray(new String[] {"a", "b", "cat"});
|
||||
out.writeBytesReference(new BytesArray("test"));
|
||||
out.writeOptionalBytesReference(new BytesArray("test"));
|
||||
final byte[] bytes = out.bytes().toBytes();
|
||||
StreamInput in = StreamInput.wrap(out.bytes().toBytes());
|
||||
assertEquals(in.available(), bytes.length);
|
||||
|
@ -296,6 +301,10 @@ public class BytesStreamsTests extends ESTestCase {
|
|||
assertThat(in.readString(), equalTo("hello"));
|
||||
assertThat(in.readString(), equalTo("goodbye"));
|
||||
assertThat(in.readGenericValue(), equalTo((Object)BytesRefs.toBytesRef("bytesref")));
|
||||
assertThat(in.readStringArray(), equalTo(new String[] {"a", "b", "cat"}));
|
||||
assertThat(in.readBytesReference(), equalTo(new BytesArray("test")));
|
||||
assertThat(in.readOptionalBytesReference(), equalTo(new BytesArray("test")));
|
||||
assertEquals(0, in.available());
|
||||
in.close();
|
||||
out.close();
|
||||
}
|
||||
|
|
|
@ -255,11 +255,6 @@ public abstract class AbstractQueryTestCase<QB extends AbstractQueryBuilder<QB>>
|
|||
protected void configureSearch() {
|
||||
// Skip me
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configureSuggesters() {
|
||||
// Skip me
|
||||
}
|
||||
},
|
||||
new AbstractModule() {
|
||||
@Override
|
||||
|
|
|
@ -48,7 +48,7 @@ public class SearchModuleTests extends ModuleTestCase {
|
|||
}
|
||||
|
||||
try {
|
||||
module.registerSuggester("term", PhraseSuggester.PROTOTYPE);
|
||||
module.registerSuggester("term", PhraseSuggester.INSTANCE);
|
||||
} catch (IllegalArgumentException e) {
|
||||
assertEquals(e.getMessage(), "Can't register the same [suggester] more than once for [term]");
|
||||
}
|
||||
|
@ -57,12 +57,9 @@ public class SearchModuleTests extends ModuleTestCase {
|
|||
public void testRegisterSuggester() {
|
||||
SearchModule module = new SearchModule(Settings.EMPTY, new NamedWriteableRegistry());
|
||||
module.registerSuggester("custom", CustomSuggester.PROTOTYPE);
|
||||
try {
|
||||
module.registerSuggester("custom", CustomSuggester.PROTOTYPE);
|
||||
} catch (IllegalArgumentException e) {
|
||||
assertEquals(e.getMessage(), "Can't register the same [suggester] more than once for [custom]");
|
||||
}
|
||||
assertMapMultiBinding(module, Suggester.class, CustomSuggester.class);
|
||||
IllegalArgumentException e = expectThrows(IllegalArgumentException.class,
|
||||
() -> module.registerSuggester("custom", CustomSuggester.PROTOTYPE));
|
||||
assertEquals("Can't register the same [suggester] more than once for [custom]", e.getMessage());
|
||||
}
|
||||
|
||||
public void testRegisterHighlighter() {
|
||||
|
|
|
@ -159,11 +159,6 @@ public class AggregatorParsingTests extends ESTestCase {
|
|||
protected void configureSearch() {
|
||||
// Skip me
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configureSuggesters() {
|
||||
// Skip me
|
||||
}
|
||||
}, new IndexSettingsModule(index, settings),
|
||||
|
||||
new AbstractModule() {
|
||||
|
|
|
@ -173,11 +173,6 @@ public abstract class BaseAggregationTestCase<AB extends AggregatorBuilder<AB>>
|
|||
protected void configureSearch() {
|
||||
// Skip me
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configureSuggesters() {
|
||||
// Skip me
|
||||
}
|
||||
},
|
||||
new IndexSettingsModule(index, settings),
|
||||
|
||||
|
|
|
@ -174,11 +174,6 @@ public abstract class BasePipelineAggregationTestCase<AF extends PipelineAggrega
|
|||
protected void configureSearch() {
|
||||
// Skip me
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configureSuggesters() {
|
||||
// Skip me
|
||||
}
|
||||
},
|
||||
new IndexSettingsModule(index, settings),
|
||||
new AbstractModule() {
|
||||
|
|
|
@ -213,6 +213,7 @@ public class SearchSourceBuilderTests extends ESTestCase {
|
|||
injector = null;
|
||||
index = null;
|
||||
aggParsers = null;
|
||||
suggesters = null;
|
||||
currentTypes = null;
|
||||
namedWriteableRegistry = null;
|
||||
}
|
||||
|
|
|
@ -31,26 +31,15 @@ import org.elasticsearch.common.xcontent.XContentFactory;
|
|||
import org.elasticsearch.common.xcontent.XContentHelper;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.common.xcontent.XContentType;
|
||||
import org.elasticsearch.env.Environment;
|
||||
import org.elasticsearch.index.query.QueryParseContext;
|
||||
import org.elasticsearch.indices.query.IndicesQueriesRegistry;
|
||||
import org.elasticsearch.script.ScriptContextRegistry;
|
||||
import org.elasticsearch.script.ScriptEngineRegistry;
|
||||
import org.elasticsearch.script.ScriptServiceTests.TestEngineService;
|
||||
import org.elasticsearch.script.ScriptSettings;
|
||||
import org.elasticsearch.search.SearchModule;
|
||||
import org.elasticsearch.search.suggest.completion.CompletionSuggestionBuilder;
|
||||
import org.elasticsearch.search.suggest.phrase.PhraseSuggestionBuilder;
|
||||
import org.elasticsearch.search.suggest.term.TermSuggestionBuilder;
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Collections;
|
||||
|
||||
import static org.elasticsearch.common.settings.Settings.settingsBuilder;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.not;
|
||||
|
||||
|
@ -67,23 +56,10 @@ public abstract class AbstractSuggestionBuilderTestCase<SB extends SuggestionBui
|
|||
*/
|
||||
@BeforeClass
|
||||
public static void init() throws IOException {
|
||||
Path genericConfigFolder = createTempDir();
|
||||
Settings baseSettings = settingsBuilder()
|
||||
.put(Environment.PATH_HOME_SETTING.getKey(), createTempDir().toString())
|
||||
.put(Environment.PATH_CONF_SETTING.getKey(), genericConfigFolder)
|
||||
.build();
|
||||
Environment environment = new Environment(baseSettings);
|
||||
ScriptContextRegistry scriptContextRegistry = new ScriptContextRegistry(Collections.emptyList());
|
||||
ScriptEngineRegistry scriptEngineRegistry = new ScriptEngineRegistry(Collections.singletonList(new ScriptEngineRegistry
|
||||
.ScriptEngineRegistration(TestEngineService.class, TestEngineService.TYPES)));
|
||||
ScriptSettings scriptSettings = new ScriptSettings(scriptEngineRegistry, scriptContextRegistry);
|
||||
suggesters = new Suggesters(Collections.emptyMap());
|
||||
|
||||
namedWriteableRegistry = new NamedWriteableRegistry();
|
||||
namedWriteableRegistry.registerPrototype(SuggestionBuilder.class, TermSuggestionBuilder.PROTOTYPE);
|
||||
namedWriteableRegistry.registerPrototype(SuggestionBuilder.class, PhraseSuggestionBuilder.PROTOTYPE);
|
||||
namedWriteableRegistry.registerPrototype(SuggestionBuilder.class, CompletionSuggestionBuilder.PROTOTYPE);
|
||||
queriesRegistry = new SearchModule(Settings.EMPTY, namedWriteableRegistry).buildQueryParserRegistry();
|
||||
SearchModule searchModule = new SearchModule(Settings.EMPTY, namedWriteableRegistry);
|
||||
queriesRegistry = searchModule.buildQueryParserRegistry();
|
||||
suggesters = searchModule.getSuggesters();
|
||||
parseFieldMatcher = ParseFieldMatcher.STRICT;
|
||||
}
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@ import org.elasticsearch.action.search.SearchResponse;
|
|||
import org.elasticsearch.common.geo.GeoPoint;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.unit.Fuzziness;
|
||||
import org.elasticsearch.common.xcontent.ToXContent;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.search.suggest.CompletionSuggestSearchIT.CompletionMappingBuilder;
|
||||
import org.elasticsearch.search.suggest.completion.CompletionSuggestionBuilder;
|
||||
|
@ -36,7 +37,6 @@ import org.elasticsearch.search.suggest.completion.context.ContextBuilder;
|
|||
import org.elasticsearch.search.suggest.completion.context.ContextMapping;
|
||||
import org.elasticsearch.search.suggest.completion.context.GeoContextMapping;
|
||||
import org.elasticsearch.search.suggest.completion.context.GeoQueryContext;
|
||||
import org.elasticsearch.search.suggest.completion.context.QueryContext;
|
||||
import org.elasticsearch.test.ESIntegTestCase;
|
||||
|
||||
import java.io.IOException;
|
||||
|
@ -280,7 +280,7 @@ public class ContextCompletionSuggestSearchIT extends ESIntegTestCase {
|
|||
|
||||
CompletionSuggestionBuilder multiContextFilterSuggest = SuggestBuilders.completionSuggestion(FIELD).prefix("sugg");
|
||||
// query context order should never matter
|
||||
Map<String, List<? extends QueryContext>> contextMap = new HashMap<>();
|
||||
Map<String, List<? extends ToXContent>> contextMap = new HashMap<>();
|
||||
contextMap.put("type", Collections.singletonList(CategoryQueryContext.builder().setCategory("type2").build()));
|
||||
contextMap.put("cat", Collections.singletonList(CategoryQueryContext.builder().setCategory("cat2").build()));
|
||||
multiContextFilterSuggest.contexts(contextMap);
|
||||
|
@ -331,7 +331,7 @@ public class ContextCompletionSuggestSearchIT extends ESIntegTestCase {
|
|||
// boost on both contexts
|
||||
CompletionSuggestionBuilder multiContextBoostSuggest = SuggestBuilders.completionSuggestion(FIELD).prefix("sugg");
|
||||
// query context order should never matter
|
||||
Map<String, List<? extends QueryContext>> contextMap = new HashMap<>();
|
||||
Map<String, List<? extends ToXContent>> contextMap = new HashMap<>();
|
||||
contextMap.put("type", Arrays.asList(
|
||||
CategoryQueryContext.builder().setCategory("type2").setBoost(2).build(),
|
||||
CategoryQueryContext.builder().setCategory("type1").setBoost(4).build())
|
||||
|
|
|
@ -20,16 +20,16 @@ package org.elasticsearch.search.suggest;
|
|||
|
||||
import org.apache.lucene.search.IndexSearcher;
|
||||
import org.apache.lucene.util.CharsRefBuilder;
|
||||
import org.elasticsearch.common.io.stream.StreamInput;
|
||||
import org.elasticsearch.common.text.Text;
|
||||
import org.elasticsearch.index.query.QueryParseContext;
|
||||
import org.elasticsearch.index.query.QueryShardContext;
|
||||
import org.elasticsearch.search.suggest.CustomSuggesterSearchIT.CustomSuggestionBuilder;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class CustomSuggester extends Suggester<CustomSuggester.CustomSuggestionsContext> {
|
||||
|
||||
public static CustomSuggester PROTOTYPE = new CustomSuggester();
|
||||
|
@ -65,7 +65,12 @@ public class CustomSuggester extends Suggester<CustomSuggester.CustomSuggestions
|
|||
}
|
||||
|
||||
@Override
|
||||
public SuggestionBuilder<?> getBuilderPrototype() {
|
||||
return CustomSuggesterSearchIT.CustomSuggestionBuilder.PROTOTYPE;
|
||||
public SuggestionBuilder<?> innerFromXContent(QueryParseContext context) throws IOException {
|
||||
return CustomSuggestionBuilder.innerFromXContent(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SuggestionBuilder<?> read(StreamInput in) throws IOException {
|
||||
return new CustomSuggestionBuilder(in);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -102,6 +102,19 @@ public class CustomSuggesterSearchIT extends ESIntegTestCase {
|
|||
this.randomSuffix = randomSuffix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read from a stream.
|
||||
*/
|
||||
public CustomSuggestionBuilder(StreamInput in) throws IOException {
|
||||
super(in);
|
||||
this.randomSuffix = in.readString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doWriteTo(StreamOutput out) throws IOException {
|
||||
out.writeString(randomSuffix);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected XContentBuilder innerToXContent(XContentBuilder builder, Params params) throws IOException {
|
||||
builder.field(RANDOM_SUFFIX_FIELD.getPreferredName(), randomSuffix);
|
||||
|
@ -113,16 +126,6 @@ public class CustomSuggesterSearchIT extends ESIntegTestCase {
|
|||
return "custom";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doWriteTo(StreamOutput out) throws IOException {
|
||||
out.writeString(randomSuffix);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CustomSuggestionBuilder doReadFrom(StreamInput in, String field) throws IOException {
|
||||
return new CustomSuggestionBuilder(field, in.readString());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean doEquals(CustomSuggestionBuilder other) {
|
||||
return Objects.equals(randomSuffix, other.randomSuffix);
|
||||
|
@ -133,8 +136,7 @@ public class CustomSuggesterSearchIT extends ESIntegTestCase {
|
|||
return Objects.hash(randomSuffix);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected CustomSuggestionBuilder innerFromXContent(QueryParseContext parseContext) throws IOException {
|
||||
static CustomSuggestionBuilder innerFromXContent(QueryParseContext parseContext) throws IOException {
|
||||
XContentParser parser = parseContext.parser();
|
||||
ParseFieldMatcher parseFieldMatcher = parseContext.parseFieldMatcher();
|
||||
XContentParser.Token token;
|
||||
|
|
|
@ -51,25 +51,21 @@ import java.util.Map.Entry;
|
|||
public class SuggestBuilderTests extends WritableTestCase<SuggestBuilder> {
|
||||
|
||||
private static NamedWriteableRegistry namedWriteableRegistry;
|
||||
private static Suggesters suggesters;
|
||||
|
||||
/**
|
||||
* Setup for the whole base test class.
|
||||
*/
|
||||
@BeforeClass
|
||||
public static void init() {
|
||||
NamedWriteableRegistry nwRegistry = new NamedWriteableRegistry();
|
||||
nwRegistry.registerPrototype(SuggestionBuilder.class, TermSuggestionBuilder.PROTOTYPE);
|
||||
nwRegistry.registerPrototype(SuggestionBuilder.class, PhraseSuggestionBuilder.PROTOTYPE);
|
||||
nwRegistry.registerPrototype(SuggestionBuilder.class, CompletionSuggestionBuilder.PROTOTYPE);
|
||||
nwRegistry.registerPrototype(SmoothingModel.class, Laplace.PROTOTYPE);
|
||||
nwRegistry.registerPrototype(SmoothingModel.class, LinearInterpolation.PROTOTYPE);
|
||||
nwRegistry.registerPrototype(SmoothingModel.class, StupidBackoff.PROTOTYPE);
|
||||
namedWriteableRegistry = nwRegistry;
|
||||
namedWriteableRegistry = new NamedWriteableRegistry();
|
||||
suggesters = new Suggesters(namedWriteableRegistry);
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void afterClass() {
|
||||
namedWriteableRegistry = null;
|
||||
suggesters = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -81,7 +77,6 @@ public class SuggestBuilderTests extends WritableTestCase<SuggestBuilder> {
|
|||
* creates random suggestion builder, renders it to xContent and back to new instance that should be equal to original
|
||||
*/
|
||||
public void testFromXContent() throws IOException {
|
||||
Suggesters suggesters = new Suggesters(Collections.emptyMap());
|
||||
QueryParseContext context = new QueryParseContext(null);
|
||||
context.parseFieldMatcher(new ParseFieldMatcher(Settings.EMPTY));
|
||||
for (int runs = 0; runs < NUMBER_OF_RUNS; runs++) {
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
package org.elasticsearch.search.suggest.completion;
|
||||
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.search.suggest.completion.context.CategoryQueryContext;
|
||||
|
||||
import java.io.IOException;
|
||||
|
@ -39,8 +40,8 @@ public class CategoryQueryContextTests extends QueryContextTestCase<CategoryQuer
|
|||
}
|
||||
|
||||
@Override
|
||||
protected CategoryQueryContext prototype() {
|
||||
return CategoryQueryContext.PROTOTYPE;
|
||||
protected CategoryQueryContext fromXContent(XContentParser parser) throws IOException {
|
||||
return CategoryQueryContext.fromXContent(parser);
|
||||
}
|
||||
|
||||
public void testNullCategoryIsIllegal() {
|
||||
|
|
|
@ -20,21 +20,14 @@
|
|||
package org.elasticsearch.search.suggest.completion;
|
||||
|
||||
import com.carrotsearch.randomizedtesting.generators.RandomStrings;
|
||||
|
||||
import org.elasticsearch.common.ParsingException;
|
||||
import org.elasticsearch.common.collect.Tuple;
|
||||
import org.elasticsearch.common.unit.Fuzziness;
|
||||
import org.elasticsearch.index.mapper.MappedFieldType;
|
||||
import org.elasticsearch.index.mapper.core.CompletionFieldMapper;
|
||||
import org.elasticsearch.common.xcontent.ToXContent;
|
||||
import org.elasticsearch.search.suggest.AbstractSuggestionBuilderTestCase;
|
||||
import org.elasticsearch.search.suggest.SuggestBuilder;
|
||||
import org.elasticsearch.search.suggest.SuggestionSearchContext.SuggestionContext;
|
||||
import org.elasticsearch.search.suggest.completion.context.CategoryContextMapping;
|
||||
import org.elasticsearch.search.suggest.completion.context.CategoryQueryContext;
|
||||
import org.elasticsearch.search.suggest.completion.context.ContextMapping;
|
||||
import org.elasticsearch.search.suggest.completion.context.ContextMappings;
|
||||
import org.elasticsearch.search.suggest.completion.context.GeoContextMapping;
|
||||
import org.elasticsearch.search.suggest.completion.context.GeoQueryContext;
|
||||
import org.elasticsearch.search.suggest.completion.context.QueryContext;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
|
@ -43,9 +36,7 @@ import java.util.HashMap;
|
|||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.hamcrest.core.IsInstanceOf.instanceOf;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
|
||||
public class CompletionSuggesterBuilderTests extends AbstractSuggestionBuilderTestCase<CompletionSuggestionBuilder> {
|
||||
|
@ -86,7 +77,7 @@ public class CompletionSuggesterBuilderTests extends AbstractSuggestionBuilderTe
|
|||
List<String> payloads = new ArrayList<>();
|
||||
Collections.addAll(payloads, generateRandomStringArray(5, 10, false, false));
|
||||
maybeSet(testBuilder::payload, payloads);
|
||||
Map<String, List<? extends QueryContext>> contextMap = new HashMap<>();
|
||||
Map<String, List<? extends ToXContent>> contextMap = new HashMap<>();
|
||||
if (randomBoolean()) {
|
||||
int numContext = randomIntBetween(1, 5);
|
||||
List<CategoryQueryContext> contexts = new ArrayList<>(numContext);
|
||||
|
|
|
@ -83,7 +83,7 @@ public class FuzzyOptionsTests extends WritableTestCase<FuzzyOptions> {
|
|||
|
||||
@Override
|
||||
protected FuzzyOptions readFrom(StreamInput in) throws IOException {
|
||||
return FuzzyOptions.readFuzzyOptions(in);
|
||||
return new FuzzyOptions(in);
|
||||
}
|
||||
|
||||
public void testIllegalArguments() {
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
package org.elasticsearch.search.suggest.completion;
|
||||
|
||||
import org.elasticsearch.common.geo.GeoPoint;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.search.suggest.completion.context.GeoQueryContext;
|
||||
|
||||
import java.io.IOException;
|
||||
|
@ -50,8 +51,8 @@ public class GeoQueryContextTests extends QueryContextTestCase<GeoQueryContext>
|
|||
}
|
||||
|
||||
@Override
|
||||
protected GeoQueryContext prototype() {
|
||||
return GeoQueryContext.PROTOTYPE;
|
||||
protected GeoQueryContext fromXContent(XContentParser parser) throws IOException {
|
||||
return GeoQueryContext.fromXContent(parser);
|
||||
}
|
||||
|
||||
public void testNullGeoPointIsIllegal() {
|
||||
|
|
|
@ -20,21 +20,16 @@
|
|||
package org.elasticsearch.search.suggest.completion;
|
||||
|
||||
import org.elasticsearch.common.bytes.BytesReference;
|
||||
import org.elasticsearch.common.io.stream.StreamInput;
|
||||
import org.elasticsearch.common.xcontent.ToXContent;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.common.xcontent.XContentFactory;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.search.suggest.completion.context.QueryContext;
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import static junit.framework.TestCase.assertEquals;
|
||||
|
||||
|
||||
public abstract class QueryContextTestCase<QC extends QueryContext> extends ESTestCase {
|
||||
|
||||
public abstract class QueryContextTestCase<QC extends ToXContent> extends ESTestCase {
|
||||
private static final int NUMBER_OF_RUNS = 20;
|
||||
|
||||
/**
|
||||
|
@ -43,19 +38,19 @@ public abstract class QueryContextTestCase<QC extends QueryContext> extends ESTe
|
|||
protected abstract QC createTestModel();
|
||||
|
||||
/**
|
||||
* query context prototype to read serialized format
|
||||
* read the context
|
||||
*/
|
||||
protected abstract QC prototype();
|
||||
protected abstract QC fromXContent(XContentParser parser) throws IOException;
|
||||
|
||||
public void testToXContext() throws IOException {
|
||||
for (int i = 0; i < NUMBER_OF_RUNS; i++) {
|
||||
QueryContext toXContent = createTestModel();
|
||||
QC toXContent = createTestModel();
|
||||
XContentBuilder builder = XContentFactory.jsonBuilder();
|
||||
toXContent.toXContent(builder, ToXContent.EMPTY_PARAMS);
|
||||
BytesReference bytesReference = builder.bytes();
|
||||
XContentParser parser = XContentFactory.xContent(bytesReference).createParser(bytesReference);
|
||||
parser.nextToken();
|
||||
QueryContext fromXContext = prototype().fromXContext(parser);
|
||||
QC fromXContext = fromXContent(parser);
|
||||
assertEquals(toXContent, fromXContext);
|
||||
assertEquals(toXContent.hashCode(), fromXContext.hashCode());
|
||||
}
|
||||
|
|
|
@ -56,7 +56,7 @@ public class RegexOptionsTests extends WritableTestCase<RegexOptions> {
|
|||
|
||||
@Override
|
||||
protected RegexOptions readFrom(StreamInput in) throws IOException {
|
||||
return RegexOptions.readRegexOptions(in);
|
||||
return new RegexOptions(in);
|
||||
}
|
||||
|
||||
public void testIllegalArgument() {
|
||||
|
|
|
@ -50,7 +50,7 @@ public abstract class WritableTestCase<M extends Writeable> extends ESTestCase {
|
|||
protected abstract M createMutation(M original) throws IOException;
|
||||
|
||||
/**
|
||||
* model prototype to read serialized format
|
||||
* Read from a stream.
|
||||
*/
|
||||
protected abstract M readFrom(StreamInput in) throws IOException;
|
||||
|
||||
|
|
|
@ -36,7 +36,6 @@ import org.elasticsearch.search.suggest.phrase.PhraseSuggestionContext.DirectCan
|
|||
import org.elasticsearch.test.ESTestCase;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
|
@ -125,8 +124,7 @@ public class DirectCandidateGeneratorTests extends ESTestCase{
|
|||
XContentParser parser = XContentHelper.createParser(builder.bytes());
|
||||
context.reset(parser);
|
||||
parser.nextToken();
|
||||
DirectCandidateGeneratorBuilder secondGenerator = DirectCandidateGeneratorBuilder.PROTOTYPE
|
||||
.fromXContent(context);
|
||||
DirectCandidateGeneratorBuilder secondGenerator = DirectCandidateGeneratorBuilder.fromXContent(context);
|
||||
assertNotSame(generator, secondGenerator);
|
||||
assertEquals(generator, secondGenerator);
|
||||
assertEquals(generator.hashCode(), secondGenerator.hashCode());
|
||||
|
@ -161,62 +159,37 @@ public class DirectCandidateGeneratorTests extends ESTestCase{
|
|||
// test missing fieldname
|
||||
String directGenerator = "{ }";
|
||||
XContentParser parser = XContentFactory.xContent(directGenerator).createParser(directGenerator);
|
||||
|
||||
context.reset(parser);
|
||||
try {
|
||||
DirectCandidateGeneratorBuilder.PROTOTYPE.fromXContent(context);
|
||||
fail("expected an exception");
|
||||
} catch (IllegalArgumentException e) {
|
||||
assertEquals("[direct_generator] expects exactly one field parameter, but found []", e.getMessage());
|
||||
}
|
||||
Exception e = expectThrows(IllegalArgumentException.class, () -> DirectCandidateGeneratorBuilder.fromXContent(context));
|
||||
assertEquals("[direct_generator] expects exactly one field parameter, but found []", e.getMessage());
|
||||
|
||||
// test two fieldnames
|
||||
directGenerator = "{ \"field\" : \"f1\", \"field\" : \"f2\" }";
|
||||
parser = XContentFactory.xContent(directGenerator).createParser(directGenerator);
|
||||
|
||||
context.reset(parser);
|
||||
try {
|
||||
DirectCandidateGeneratorBuilder.PROTOTYPE.fromXContent(context);
|
||||
fail("expected an exception");
|
||||
} catch (IllegalArgumentException e) {
|
||||
assertEquals("[direct_generator] expects exactly one field parameter, but found [f2, f1]", e.getMessage());
|
||||
}
|
||||
e = expectThrows(IllegalArgumentException.class, () -> DirectCandidateGeneratorBuilder.fromXContent(context));
|
||||
assertEquals("[direct_generator] expects exactly one field parameter, but found [f2, f1]", e.getMessage());
|
||||
|
||||
// test unknown field
|
||||
directGenerator = "{ \"unknown_param\" : \"f1\" }";
|
||||
parser = XContentFactory.xContent(directGenerator).createParser(directGenerator);
|
||||
|
||||
context.reset(parser);
|
||||
try {
|
||||
DirectCandidateGeneratorBuilder.PROTOTYPE.fromXContent(context);
|
||||
fail("expected an exception");
|
||||
} catch (IllegalArgumentException e) {
|
||||
assertEquals("[direct_generator] unknown field [unknown_param], parser not found", e.getMessage());
|
||||
}
|
||||
e = expectThrows(IllegalArgumentException.class, () -> DirectCandidateGeneratorBuilder.fromXContent(context));
|
||||
assertEquals("[direct_generator] unknown field [unknown_param], parser not found", e.getMessage());
|
||||
|
||||
// test bad value for field (e.g. size expects an int)
|
||||
directGenerator = "{ \"size\" : \"xxl\" }";
|
||||
parser = XContentFactory.xContent(directGenerator).createParser(directGenerator);
|
||||
|
||||
context.reset(parser);
|
||||
try {
|
||||
DirectCandidateGeneratorBuilder.PROTOTYPE.fromXContent(context);
|
||||
fail("expected an exception");
|
||||
} catch (ParsingException e) {
|
||||
assertEquals("[direct_generator] failed to parse field [size]", e.getMessage());
|
||||
}
|
||||
e = expectThrows(ParsingException.class, () -> DirectCandidateGeneratorBuilder.fromXContent(context));
|
||||
assertEquals("[direct_generator] failed to parse field [size]", e.getMessage());
|
||||
|
||||
// test unexpected token
|
||||
directGenerator = "{ \"size\" : [ \"xxl\" ] }";
|
||||
parser = XContentFactory.xContent(directGenerator).createParser(directGenerator);
|
||||
|
||||
context.reset(parser);
|
||||
try {
|
||||
DirectCandidateGeneratorBuilder.PROTOTYPE.fromXContent(context);
|
||||
fail("expected an exception");
|
||||
} catch (IllegalArgumentException e) {
|
||||
assertEquals("[direct_generator] size doesn't support values of type: START_ARRAY", e.getMessage());
|
||||
}
|
||||
e = expectThrows(IllegalArgumentException.class, () -> DirectCandidateGeneratorBuilder.fromXContent(context));
|
||||
assertEquals("[direct_generator] size doesn't support values of type: START_ARRAY", e.getMessage());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -234,9 +207,9 @@ public class DirectCandidateGeneratorTests extends ESTestCase{
|
|||
maybeSet(generator::preFilter, randomAsciiOfLengthBetween(1, 20));
|
||||
maybeSet(generator::postFilter, randomAsciiOfLengthBetween(1, 20));
|
||||
maybeSet(generator::size, randomIntBetween(1, 20));
|
||||
maybeSet(generator::sort, randomFrom(Arrays.asList(new String[]{ "score", "frequency" })));
|
||||
maybeSet(generator::stringDistance, randomFrom(Arrays.asList(new String[]{ "internal", "damerau_levenshtein", "levenstein", "jarowinkler", "ngram"})));
|
||||
maybeSet(generator::suggestMode, randomFrom(Arrays.asList(new String[]{ "missing", "popular", "always"})));
|
||||
maybeSet(generator::sort, randomFrom("score", "frequency"));
|
||||
maybeSet(generator::stringDistance, randomFrom("internal", "damerau_levenshtein", "levenstein", "jarowinkler", "ngram"));
|
||||
maybeSet(generator::suggestMode, randomFrom("missing", "popular", "always"));
|
||||
return generator;
|
||||
}
|
||||
|
||||
|
@ -244,7 +217,7 @@ public class DirectCandidateGeneratorTests extends ESTestCase{
|
|||
try (BytesStreamOutput output = new BytesStreamOutput()) {
|
||||
original.writeTo(output);
|
||||
try (StreamInput in = StreamInput.wrap(output.bytes())) {
|
||||
return DirectCandidateGeneratorBuilder.PROTOTYPE.readFrom(in);
|
||||
return new DirectCandidateGeneratorBuilder(in);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,6 +19,10 @@
|
|||
|
||||
package org.elasticsearch.search.suggest.phrase;
|
||||
|
||||
import org.elasticsearch.index.query.QueryParseContext;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import static org.hamcrest.Matchers.instanceOf;
|
||||
|
||||
public class LaplaceModelTests extends SmoothingModelTestCase {
|
||||
|
@ -48,4 +52,9 @@ public class LaplaceModelTests extends SmoothingModelTestCase {
|
|||
assertThat(wordScorer, instanceOf(LaplaceScorer.class));
|
||||
assertEquals(model.getAlpha(), ((LaplaceScorer) wordScorer).alpha(), Double.MIN_VALUE);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SmoothingModel fromXContent(QueryParseContext context) throws IOException {
|
||||
return Laplace.innerFromXContent(context);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,6 +19,10 @@
|
|||
|
||||
package org.elasticsearch.search.suggest.phrase;
|
||||
|
||||
import org.elasticsearch.index.query.QueryParseContext;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import static org.hamcrest.Matchers.instanceOf;
|
||||
|
||||
public class LinearInterpolationModelTests extends SmoothingModelTestCase {
|
||||
|
@ -67,4 +71,9 @@ public class LinearInterpolationModelTests extends SmoothingModelTestCase {
|
|||
assertEquals(testModel.getBigramLambda(), (testScorer).bigramLambda(), 1e-15);
|
||||
assertEquals(testModel.getUnigramLambda(), (testScorer).unigramLambda(), 1e-15);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SmoothingModel fromXContent(QueryParseContext context) throws IOException {
|
||||
return LinearInterpolation.innerFromXContent(context);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,26 +21,12 @@ package org.elasticsearch.search.suggest.phrase;
|
|||
|
||||
import org.elasticsearch.script.Template;
|
||||
import org.elasticsearch.search.suggest.AbstractSuggestionBuilderTestCase;
|
||||
import org.elasticsearch.search.suggest.SuggestionSearchContext.SuggestionContext;
|
||||
import org.elasticsearch.search.suggest.phrase.PhraseSuggestionContext.DirectCandidateGenerator;
|
||||
import org.junit.BeforeClass;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.hamcrest.Matchers.instanceOf;
|
||||
|
||||
public class PhraseSuggestionBuilderTests extends AbstractSuggestionBuilderTestCase<PhraseSuggestionBuilder> {
|
||||
|
||||
@BeforeClass
|
||||
public static void initSmoothingModels() {
|
||||
namedWriteableRegistry.registerPrototype(SmoothingModel.class, Laplace.PROTOTYPE);
|
||||
namedWriteableRegistry.registerPrototype(SmoothingModel.class, LinearInterpolation.PROTOTYPE);
|
||||
namedWriteableRegistry.registerPrototype(SmoothingModel.class, StupidBackoff.PROTOTYPE);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PhraseSuggestionBuilder randomSuggestionBuilder() {
|
||||
return randomPhraseSuggestionBuilder();
|
||||
|
@ -162,81 +148,40 @@ public class PhraseSuggestionBuilderTests extends AbstractSuggestionBuilderTestC
|
|||
|
||||
public void testInvalidParameters() throws IOException {
|
||||
// test missing field name
|
||||
try {
|
||||
new PhraseSuggestionBuilder(null);
|
||||
fail("Should not allow null as field name");
|
||||
} catch (NullPointerException e) {
|
||||
assertEquals("suggestion requires a field name", e.getMessage());
|
||||
}
|
||||
Exception e = expectThrows(NullPointerException.class, () -> new PhraseSuggestionBuilder((String) null));
|
||||
assertEquals("suggestion requires a field name", e.getMessage());
|
||||
|
||||
// test emtpy field name
|
||||
try {
|
||||
new PhraseSuggestionBuilder("");
|
||||
fail("Should not allow empty string as field name");
|
||||
} catch (IllegalArgumentException e) {
|
||||
assertEquals("suggestion field name is empty", e.getMessage());
|
||||
}
|
||||
// test empty field name
|
||||
e = expectThrows(IllegalArgumentException.class, () -> new PhraseSuggestionBuilder(""));
|
||||
assertEquals("suggestion field name is empty", e.getMessage());
|
||||
|
||||
PhraseSuggestionBuilder builder = new PhraseSuggestionBuilder(randomAsciiOfLengthBetween(2, 20));
|
||||
try {
|
||||
builder.gramSize(0);
|
||||
fail("Should not allow gramSize < 1");
|
||||
} catch (IllegalArgumentException e) {
|
||||
assertEquals("gramSize must be >= 1", e.getMessage());
|
||||
}
|
||||
|
||||
try {
|
||||
builder.gramSize(-1);
|
||||
fail("Should not allow gramSize < 1");
|
||||
} catch (IllegalArgumentException e) {
|
||||
assertEquals("gramSize must be >= 1", e.getMessage());
|
||||
}
|
||||
e = expectThrows(IllegalArgumentException.class, () -> builder.gramSize(0));
|
||||
assertEquals("gramSize must be >= 1", e.getMessage());
|
||||
e = expectThrows(IllegalArgumentException.class, () -> builder.gramSize(-1));
|
||||
assertEquals("gramSize must be >= 1", e.getMessage());
|
||||
|
||||
try {
|
||||
builder.maxErrors(-1);
|
||||
fail("Should not allow maxErrors < 0");
|
||||
} catch (IllegalArgumentException e) {
|
||||
assertEquals("max_error must be > 0.0", e.getMessage());
|
||||
}
|
||||
e = expectThrows(IllegalArgumentException.class, () -> builder.maxErrors(-1));
|
||||
assertEquals("max_error must be > 0.0", e.getMessage());
|
||||
|
||||
try {
|
||||
builder.separator(null);
|
||||
fail("Should not allow null as separator");
|
||||
} catch (NullPointerException e) {
|
||||
assertEquals("separator cannot be set to null", e.getMessage());
|
||||
}
|
||||
e = expectThrows(NullPointerException.class, () -> builder.separator(null));
|
||||
assertEquals("separator cannot be set to null", e.getMessage());
|
||||
|
||||
try {
|
||||
builder.realWordErrorLikelihood(-1);
|
||||
fail("Should not allow real world error likelihood < 0");
|
||||
} catch (IllegalArgumentException e) {
|
||||
assertEquals("real_word_error_likelihood must be > 0.0", e.getMessage());
|
||||
}
|
||||
e = expectThrows(IllegalArgumentException.class, () -> builder.realWordErrorLikelihood(-1));
|
||||
assertEquals("real_word_error_likelihood must be > 0.0", e.getMessage());
|
||||
|
||||
try {
|
||||
builder.confidence(-1);
|
||||
fail("Should not allow confidence < 0");
|
||||
} catch (IllegalArgumentException e) {
|
||||
assertEquals("confidence must be >= 0.0", e.getMessage());
|
||||
}
|
||||
e = expectThrows(IllegalArgumentException.class, () -> builder.confidence(-1));
|
||||
assertEquals("confidence must be >= 0.0", e.getMessage());
|
||||
|
||||
try {
|
||||
builder.tokenLimit(0);
|
||||
fail("token_limit must be >= 1");
|
||||
} catch (IllegalArgumentException e) {
|
||||
assertEquals("token_limit must be >= 1", e.getMessage());
|
||||
}
|
||||
e = expectThrows(IllegalArgumentException.class, () -> builder.tokenLimit(0));
|
||||
assertEquals("token_limit must be >= 1", e.getMessage());
|
||||
|
||||
try {
|
||||
if (randomBoolean()) {
|
||||
builder.highlight(null, "</b>");
|
||||
} else {
|
||||
builder.highlight("<b>", null);
|
||||
}
|
||||
fail("Pre and post tag must both be null or both not be null.");
|
||||
} catch (IllegalArgumentException e) {
|
||||
assertEquals("Pre and post tag must both be null or both not be null.", e.getMessage());
|
||||
}
|
||||
e = expectThrows(IllegalArgumentException.class, () -> builder.highlight(null, "</b>"));
|
||||
assertEquals("Pre and post tag must both be null or both not be null.", e.getMessage());
|
||||
|
||||
e = expectThrows(IllegalArgumentException.class, () -> builder.highlight("<b>", null));
|
||||
assertEquals("Pre and post tag must both be null or both not be null.", e.getMessage());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -45,6 +45,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.test.ESTestCase;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
|
@ -68,9 +69,7 @@ public abstract class SmoothingModelTestCase extends ESTestCase {
|
|||
public static void init() {
|
||||
if (namedWriteableRegistry == null) {
|
||||
namedWriteableRegistry = new NamedWriteableRegistry();
|
||||
namedWriteableRegistry.registerPrototype(SmoothingModel.class, Laplace.PROTOTYPE);
|
||||
namedWriteableRegistry.registerPrototype(SmoothingModel.class, LinearInterpolation.PROTOTYPE);
|
||||
namedWriteableRegistry.registerPrototype(SmoothingModel.class, StupidBackoff.PROTOTYPE);
|
||||
new Suggesters(namedWriteableRegistry);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -89,6 +88,8 @@ public abstract class SmoothingModelTestCase extends ESTestCase {
|
|||
*/
|
||||
protected abstract SmoothingModel createMutation(SmoothingModel original) throws IOException;
|
||||
|
||||
protected abstract SmoothingModel fromXContent(QueryParseContext context) throws IOException;
|
||||
|
||||
/**
|
||||
* Test that creates new smoothing model from a random test smoothing model and checks both for equality
|
||||
*/
|
||||
|
@ -108,7 +109,7 @@ public abstract class SmoothingModelTestCase extends ESTestCase {
|
|||
XContentParser parser = XContentHelper.createParser(contentBuilder.bytes());
|
||||
context.reset(parser);
|
||||
parser.nextToken(); // go to start token, real parsing would do that in the outer element parser
|
||||
SmoothingModel parsedModel = testModel.innerFromXContent(context);
|
||||
SmoothingModel parsedModel = fromXContent(context);
|
||||
assertNotSame(testModel, parsedModel);
|
||||
assertEquals(testModel, parsedModel);
|
||||
assertEquals(testModel.hashCode(), parsedModel.hashCode());
|
||||
|
|
|
@ -19,6 +19,10 @@
|
|||
|
||||
package org.elasticsearch.search.suggest.phrase;
|
||||
|
||||
import org.elasticsearch.index.query.QueryParseContext;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import static org.hamcrest.Matchers.instanceOf;
|
||||
|
||||
public class StupidBackoffModelTests extends SmoothingModelTestCase {
|
||||
|
@ -47,4 +51,9 @@ public class StupidBackoffModelTests extends SmoothingModelTestCase {
|
|||
StupidBackoff testModel = (StupidBackoff) input;
|
||||
assertEquals(testModel.getDiscount(), ((StupidBackoffScorer) wordScorer).discount(), Double.MIN_VALUE);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SmoothingModel fromXContent(QueryParseContext context) throws IOException {
|
||||
return StupidBackoff.innerFromXContent(context);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
package org.elasticsearch.search.suggest.term;
|
||||
|
||||
import org.elasticsearch.common.io.stream.AbstractWriteableEnumTestCase;
|
||||
import org.elasticsearch.common.io.stream.StreamInput;
|
||||
import org.elasticsearch.search.suggest.SortBy;
|
||||
|
||||
import java.io.IOException;
|
||||
|
@ -30,6 +31,9 @@ import static org.hamcrest.Matchers.equalTo;
|
|||
* Test the {@link SortBy} enum.
|
||||
*/
|
||||
public class SortByTests extends AbstractWriteableEnumTestCase {
|
||||
public SortByTests() {
|
||||
super(SortBy::readFromStream);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void testValidOrdinals() {
|
||||
|
@ -66,5 +70,4 @@ public class SortByTests extends AbstractWriteableEnumTestCase {
|
|||
assertReadFromStream(0, SortBy.SCORE);
|
||||
assertReadFromStream(1, SortBy.FREQUENCY);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -30,6 +30,9 @@ import static org.hamcrest.Matchers.equalTo;
|
|||
* Test for the {@link StringDistanceImpl} enum.
|
||||
*/
|
||||
public class StringDistanceImplTests extends AbstractWriteableEnumTestCase {
|
||||
public StringDistanceImplTests() {
|
||||
super(StringDistanceImpl::readFromStream);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void testValidOrdinals() {
|
||||
|
|
|
@ -30,6 +30,9 @@ import static org.hamcrest.Matchers.equalTo;
|
|||
* Test the {@link SuggestMode} enum.
|
||||
*/
|
||||
public class SuggestModeTests extends AbstractWriteableEnumTestCase {
|
||||
public SuggestModeTests() {
|
||||
super(SuggestMode::readFromStream);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void testValidOrdinals() {
|
||||
|
|
|
@ -20,11 +20,11 @@
|
|||
package org.elasticsearch.search.suggest.term;
|
||||
|
||||
import com.carrotsearch.randomizedtesting.generators.RandomStrings;
|
||||
|
||||
import org.elasticsearch.search.suggest.AbstractSuggestionBuilderTestCase;
|
||||
import org.elasticsearch.search.suggest.DirectSpellcheckerSettings;
|
||||
import org.elasticsearch.search.suggest.SortBy;
|
||||
import org.elasticsearch.search.suggest.SuggestBuilder;
|
||||
import org.elasticsearch.search.suggest.SuggestionSearchContext.SuggestionContext;
|
||||
import org.elasticsearch.search.suggest.term.TermSuggestionBuilder.StringDistanceImpl;
|
||||
import org.elasticsearch.search.suggest.term.TermSuggestionBuilder.SuggestMode;
|
||||
|
||||
|
@ -143,131 +143,52 @@ public class TermSuggestionBuilderTests extends AbstractSuggestionBuilderTestCas
|
|||
|
||||
public void testInvalidParameters() throws IOException {
|
||||
// test missing field name
|
||||
try {
|
||||
new TermSuggestionBuilder(null);
|
||||
fail("Should not allow null as field name");
|
||||
} catch (NullPointerException e) {
|
||||
assertEquals("suggestion requires a field name", e.getMessage());
|
||||
}
|
||||
Exception e = expectThrows(NullPointerException.class, () -> new TermSuggestionBuilder((String) null));
|
||||
assertEquals("suggestion requires a field name", e.getMessage());
|
||||
|
||||
// test emtpy field name
|
||||
try {
|
||||
new TermSuggestionBuilder("");
|
||||
fail("Should not allow empty string as field name");
|
||||
} catch (IllegalArgumentException e) {
|
||||
assertEquals("suggestion field name is empty", e.getMessage());
|
||||
}
|
||||
// test empty field name
|
||||
e = expectThrows(IllegalArgumentException.class, () -> new TermSuggestionBuilder(""));
|
||||
assertEquals("suggestion field name is empty", e.getMessage());
|
||||
|
||||
TermSuggestionBuilder builder = new TermSuggestionBuilder(randomAsciiOfLengthBetween(2, 20));
|
||||
|
||||
// test invalid accuracy values
|
||||
try {
|
||||
builder.accuracy(-0.5f);
|
||||
fail("Should not allow accuracy to be set to a negative value.");
|
||||
} catch (IllegalArgumentException e) {
|
||||
}
|
||||
try {
|
||||
builder.accuracy(1.1f);
|
||||
fail("Should not allow accuracy to be greater than 1.0.");
|
||||
} catch (IllegalArgumentException e) {
|
||||
}
|
||||
expectThrows(IllegalArgumentException.class, () -> builder.accuracy(-0.5f));
|
||||
expectThrows(IllegalArgumentException.class, () -> builder.accuracy(1.1f));
|
||||
|
||||
// test invalid max edit distance values
|
||||
try {
|
||||
builder.maxEdits(0);
|
||||
fail("Should not allow maxEdits to be less than 1.");
|
||||
} catch (IllegalArgumentException e) {
|
||||
}
|
||||
try {
|
||||
builder.maxEdits(-1);
|
||||
fail("Should not allow maxEdits to be a negative value.");
|
||||
} catch (IllegalArgumentException e) {
|
||||
}
|
||||
try {
|
||||
builder.maxEdits(3);
|
||||
fail("Should not allow maxEdits to be greater than 2.");
|
||||
} catch (IllegalArgumentException e) {
|
||||
}
|
||||
expectThrows(IllegalArgumentException.class, () -> builder.maxEdits(0));
|
||||
expectThrows(IllegalArgumentException.class, () -> builder.maxEdits(-1));
|
||||
expectThrows(IllegalArgumentException.class, () -> builder.maxEdits(3));
|
||||
|
||||
// test invalid max inspections values
|
||||
try {
|
||||
builder.maxInspections(-1);
|
||||
fail("Should not allow maxInspections to be a negative value.");
|
||||
} catch (IllegalArgumentException e) {
|
||||
}
|
||||
expectThrows(IllegalArgumentException.class, () -> builder.maxInspections(-1));
|
||||
|
||||
// test invalid max term freq values
|
||||
try {
|
||||
builder.maxTermFreq(-0.5f);
|
||||
fail("Should not allow max term freq to be a negative value.");
|
||||
} catch (IllegalArgumentException e) {
|
||||
}
|
||||
try {
|
||||
builder.maxTermFreq(1.5f);
|
||||
fail("If max term freq is greater than 1, it must be a whole number.");
|
||||
} catch (IllegalArgumentException e) {
|
||||
}
|
||||
try {
|
||||
builder.maxTermFreq(2.0f); // this should be allowed
|
||||
} catch (IllegalArgumentException e) {
|
||||
fail("A max term freq greater than 1 that is a whole number should be allowed.");
|
||||
}
|
||||
expectThrows(IllegalArgumentException.class, () -> builder.maxTermFreq(-0.5f));
|
||||
expectThrows(IllegalArgumentException.class, () -> builder.maxTermFreq(1.5f));
|
||||
builder.maxTermFreq(2.0f);
|
||||
|
||||
// test invalid min doc freq values
|
||||
try {
|
||||
builder.minDocFreq(-0.5f);
|
||||
fail("Should not allow min doc freq to be a negative value.");
|
||||
} catch (IllegalArgumentException e) {
|
||||
}
|
||||
try {
|
||||
builder.minDocFreq(1.5f);
|
||||
fail("If min doc freq is greater than 1, it must be a whole number.");
|
||||
} catch (IllegalArgumentException e) {
|
||||
}
|
||||
try {
|
||||
builder.minDocFreq(2.0f); // this should be allowed
|
||||
} catch (IllegalArgumentException e) {
|
||||
fail("A min doc freq greater than 1 that is a whole number should be allowed.");
|
||||
}
|
||||
expectThrows(IllegalArgumentException.class, () -> builder.minDocFreq(-0.5f));
|
||||
expectThrows(IllegalArgumentException.class, () -> builder.minDocFreq(1.5f));
|
||||
builder.minDocFreq(2.0f);
|
||||
|
||||
// test invalid min word length values
|
||||
try {
|
||||
builder.minWordLength(0);
|
||||
fail("A min word length < 1 should not be allowed.");
|
||||
} catch (IllegalArgumentException e) {
|
||||
}
|
||||
try {
|
||||
builder.minWordLength(-1);
|
||||
fail("Should not allow min word length to be a negative value.");
|
||||
} catch (IllegalArgumentException e) {
|
||||
}
|
||||
expectThrows(IllegalArgumentException.class, () -> builder.minWordLength(0));
|
||||
expectThrows(IllegalArgumentException.class, () -> builder.minWordLength(-1));
|
||||
|
||||
// test invalid prefix length values
|
||||
try {
|
||||
builder.prefixLength(-1);
|
||||
fail("Should not allow prefix length to be a negative value.");
|
||||
} catch (IllegalArgumentException e) {
|
||||
}
|
||||
expectThrows(IllegalArgumentException.class, () -> builder.prefixLength(-1));
|
||||
|
||||
// test invalid size values
|
||||
try {
|
||||
builder.size(0);
|
||||
fail("Size must be a positive value.");
|
||||
} catch (IllegalArgumentException e) {
|
||||
}
|
||||
try {
|
||||
builder.size(-1);
|
||||
fail("Size must be a positive value.");
|
||||
} catch (IllegalArgumentException e) {
|
||||
}
|
||||
expectThrows(IllegalArgumentException.class, () -> builder.size(0));
|
||||
expectThrows(IllegalArgumentException.class, () -> builder.size(-1));
|
||||
|
||||
// null values not allowed for enums
|
||||
try {
|
||||
builder.sort(null);
|
||||
fail("Should not allow setting a null sort value.");
|
||||
} catch (NullPointerException e) {
|
||||
}
|
||||
try {
|
||||
builder.stringDistance(null);
|
||||
fail("Should not allow setting a null string distance value.");
|
||||
} catch (NullPointerException e) {
|
||||
}
|
||||
try {
|
||||
builder.suggestMode(null);
|
||||
fail("Should not allow setting a null suggest mode value.");
|
||||
} catch (NullPointerException e) {
|
||||
}
|
||||
expectThrows(NullPointerException.class, () -> builder.sort(null));
|
||||
expectThrows(NullPointerException.class, () -> builder.stringDistance(null));
|
||||
expectThrows(NullPointerException.class, () -> builder.suggestMode(null));
|
||||
}
|
||||
|
||||
public void testDefaultValuesSet() {
|
||||
|
|
|
@ -116,10 +116,6 @@ public class TemplateQueryParserTests extends ESTestCase {
|
|||
protected void configureSearch() {
|
||||
// skip so we don't need transport
|
||||
}
|
||||
@Override
|
||||
protected void configureSuggesters() {
|
||||
// skip so we don't need IndicesService
|
||||
}
|
||||
},
|
||||
scriptModule,
|
||||
new IndexSettingsModule(index, settings),
|
||||
|
|
Loading…
Reference in New Issue