diff options
Diffstat (limited to 'core/src/main/java/org/elasticsearch/search/suggest/completion/CompletionSuggestionBuilder.java')
-rw-r--r-- | core/src/main/java/org/elasticsearch/search/suggest/completion/CompletionSuggestionBuilder.java | 310 |
1 files changed, 84 insertions, 226 deletions
diff --git a/core/src/main/java/org/elasticsearch/search/suggest/completion/CompletionSuggestionBuilder.java b/core/src/main/java/org/elasticsearch/search/suggest/completion/CompletionSuggestionBuilder.java index 0bd37be128..fa8561998e 100644 --- a/core/src/main/java/org/elasticsearch/search/suggest/completion/CompletionSuggestionBuilder.java +++ b/core/src/main/java/org/elasticsearch/search/suggest/completion/CompletionSuggestionBuilder.java @@ -18,9 +18,6 @@ */ package org.elasticsearch.search.suggest.completion; -import org.apache.lucene.search.suggest.document.FuzzyCompletionQuery; -import org.apache.lucene.util.automaton.Operations; -import org.apache.lucene.util.automaton.RegExp; import org.elasticsearch.common.ParseField; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; @@ -29,11 +26,11 @@ import org.elasticsearch.common.xcontent.ToXContent; import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.index.query.QueryParseContext; import org.elasticsearch.index.query.QueryShardContext; -import org.elasticsearch.index.query.RegexpFlag; import org.elasticsearch.search.suggest.SuggestionBuilder; import org.elasticsearch.search.suggest.SuggestionSearchContext.SuggestionContext; import org.elasticsearch.search.suggest.completion.context.CategoryQueryContext; import org.elasticsearch.search.suggest.completion.context.GeoQueryContext; +import org.elasticsearch.search.suggest.completion.context.QueryContext; import java.io.IOException; import java.util.ArrayList; @@ -42,6 +39,7 @@ import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Set; /** @@ -57,9 +55,9 @@ public class CompletionSuggestionBuilder extends SuggestionBuilder<CompletionSug static final ParseField PAYLOAD_FIELD = new ParseField("payload"); static final ParseField CONTEXTS_FIELD = new ParseField("contexts", "context"); - private FuzzyOptionsBuilder fuzzyOptionsBuilder; - private RegexOptionsBuilder regexOptionsBuilder; - private final Map<String, List<ToXContent>> queryContexts = new HashMap<>(); + private FuzzyOptions fuzzyOptions; + private RegexOptions regexOptions; + private final Map<String, List<QueryContext>> queryContexts = new HashMap<>(); private final Set<String> payloadFields = new HashSet<>(); public CompletionSuggestionBuilder(String name) { @@ -67,198 +65,6 @@ public class CompletionSuggestionBuilder extends SuggestionBuilder<CompletionSug } /** - * Options for fuzzy queries - */ - public static class FuzzyOptionsBuilder implements ToXContent { - static final ParseField FUZZY_OPTIONS = new ParseField("fuzzy"); - static final ParseField TRANSPOSITION_FIELD = new ParseField("transpositions"); - static final ParseField MIN_LENGTH_FIELD = new ParseField("min_length"); - static final ParseField PREFIX_LENGTH_FIELD = new ParseField("prefix_length"); - static final ParseField UNICODE_AWARE_FIELD = new ParseField("unicode_aware"); - static final ParseField MAX_DETERMINIZED_STATES_FIELD = new ParseField("max_determinized_states"); - - private int editDistance = FuzzyCompletionQuery.DEFAULT_MAX_EDITS; - private boolean transpositions = FuzzyCompletionQuery.DEFAULT_TRANSPOSITIONS; - private int fuzzyMinLength = FuzzyCompletionQuery.DEFAULT_MIN_FUZZY_LENGTH; - private int fuzzyPrefixLength = FuzzyCompletionQuery.DEFAULT_NON_FUZZY_PREFIX; - private boolean unicodeAware = FuzzyCompletionQuery.DEFAULT_UNICODE_AWARE; - private int maxDeterminizedStates = Operations.DEFAULT_MAX_DETERMINIZED_STATES; - - public FuzzyOptionsBuilder() { - } - - /** - * Sets the level of fuzziness used to create suggestions using a {@link Fuzziness} instance. - * The default value is {@link Fuzziness#ONE} which allows for an "edit distance" of one. - */ - public FuzzyOptionsBuilder setFuzziness(int editDistance) { - this.editDistance = editDistance; - return this; - } - - /** - * Sets the level of fuzziness used to create suggestions using a {@link Fuzziness} instance. - * The default value is {@link Fuzziness#ONE} which allows for an "edit distance" of one. - */ - public FuzzyOptionsBuilder setFuzziness(Fuzziness fuzziness) { - this.editDistance = fuzziness.asDistance(); - return this; - } - - /** - * Sets if transpositions (swapping one character for another) counts as one character - * change or two. - * Defaults to true, meaning it uses the fuzzier option of counting transpositions as - * a single change. - */ - public FuzzyOptionsBuilder setTranspositions(boolean transpositions) { - this.transpositions = transpositions; - return this; - } - - /** - * Sets the minimum length of input string before fuzzy suggestions are returned, defaulting - * to 3. - */ - public FuzzyOptionsBuilder setFuzzyMinLength(int fuzzyMinLength) { - this.fuzzyMinLength = fuzzyMinLength; - return this; - } - - /** - * Sets the minimum length of the input, which is not checked for fuzzy alternatives, defaults to 1 - */ - public FuzzyOptionsBuilder setFuzzyPrefixLength(int fuzzyPrefixLength) { - this.fuzzyPrefixLength = fuzzyPrefixLength; - return this; - } - - /** - * Sets the maximum automaton states allowed for the fuzzy expansion - */ - public FuzzyOptionsBuilder setMaxDeterminizedStates(int maxDeterminizedStates) { - this.maxDeterminizedStates = maxDeterminizedStates; - return this; - } - - /** - * Set to true if all measurements (like edit distance, transpositions and lengths) are in unicode - * code points (actual letters) instead of bytes. Default is false. - */ - public FuzzyOptionsBuilder setUnicodeAware(boolean unicodeAware) { - this.unicodeAware = unicodeAware; - return this; - } - - /** - * Returns the maximum number of edits - */ - int getEditDistance() { - return editDistance; - } - - /** - * Returns if transpositions option is set - * - * if transpositions is set, then swapping one character for another counts as one edit instead of two. - */ - boolean isTranspositions() { - return transpositions; - } - - - /** - * Returns the length of input prefix after which edits are applied - */ - int getFuzzyMinLength() { - return fuzzyMinLength; - } - - /** - * Returns the minimum length of the input prefix required to apply any edits - */ - int getFuzzyPrefixLength() { - return fuzzyPrefixLength; - } - - /** - * Returns if all measurements (like edit distance, transpositions and lengths) are in unicode code - * points (actual letters) instead of bytes. - */ - boolean isUnicodeAware() { - return unicodeAware; - } - - /** - * Returns the maximum automaton states allowed for fuzzy expansion - */ - int getMaxDeterminizedStates() { - return maxDeterminizedStates; - } - - @Override - public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { - builder.startObject(FUZZY_OPTIONS.getPreferredName()); - builder.field(Fuzziness.FIELD.getPreferredName(), editDistance); - builder.field(TRANSPOSITION_FIELD.getPreferredName(), transpositions); - builder.field(MIN_LENGTH_FIELD.getPreferredName(), fuzzyMinLength); - builder.field(PREFIX_LENGTH_FIELD.getPreferredName(), fuzzyPrefixLength); - builder.field(UNICODE_AWARE_FIELD.getPreferredName(), unicodeAware); - builder.field(MAX_DETERMINIZED_STATES_FIELD.getPreferredName(), maxDeterminizedStates); - builder.endObject(); - return builder; - } - } - - /** - * Options for regular expression queries - */ - public static class RegexOptionsBuilder implements ToXContent { - static final ParseField REGEX_OPTIONS = new ParseField("regex"); - static final ParseField FLAGS_VALUE = new ParseField("flags", "flags_value"); - static final ParseField MAX_DETERMINIZED_STATES = new ParseField("max_determinized_states"); - private int flagsValue = RegExp.ALL; - private int maxDeterminizedStates = Operations.DEFAULT_MAX_DETERMINIZED_STATES; - - public RegexOptionsBuilder() { - } - - /** - * Sets the regular expression syntax flags - * see {@link RegexpFlag} - */ - public RegexOptionsBuilder setFlags(String flags) { - this.flagsValue = RegexpFlag.resolveValue(flags); - return this; - } - - /** - * Sets the maximum automaton states allowed for the regular expression expansion - */ - public RegexOptionsBuilder setMaxDeterminizedStates(int maxDeterminizedStates) { - this.maxDeterminizedStates = maxDeterminizedStates; - return this; - } - - int getFlagsValue() { - return flagsValue; - } - - int getMaxDeterminizedStates() { - return maxDeterminizedStates; - } - - @Override - public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { - builder.startObject(REGEX_OPTIONS.getPreferredName()); - builder.field(FLAGS_VALUE.getPreferredName(), flagsValue); - builder.field(MAX_DETERMINIZED_STATES.getPreferredName(), maxDeterminizedStates); - builder.endObject(); - return builder; - } - } - - /** * Sets the prefix to provide completions for. * The prefix gets analyzed by the suggest analyzer. */ @@ -273,17 +79,17 @@ public class CompletionSuggestionBuilder extends SuggestionBuilder<CompletionSug */ public CompletionSuggestionBuilder prefix(String prefix, Fuzziness fuzziness) { super.prefix(prefix); - this.fuzzyOptionsBuilder = new FuzzyOptionsBuilder().setFuzziness(fuzziness); + this.fuzzyOptions = new FuzzyOptions.Builder().setFuzziness(fuzziness).build(); return this; } /** * Same as {@link #prefix(String)} with full fuzzy options - * see {@link FuzzyOptionsBuilder} + * see {@link FuzzyOptions.Builder} */ - public CompletionSuggestionBuilder prefix(String prefix, FuzzyOptionsBuilder fuzzyOptionsBuilder) { + public CompletionSuggestionBuilder prefix(String prefix, FuzzyOptions fuzzyOptions) { super.prefix(prefix); - this.fuzzyOptionsBuilder = fuzzyOptionsBuilder; + this.fuzzyOptions = fuzzyOptions; return this; } @@ -298,11 +104,11 @@ public class CompletionSuggestionBuilder extends SuggestionBuilder<CompletionSug /** * Same as {@link #regex(String)} with full regular expression options - * see {@link RegexOptionsBuilder} + * see {@link RegexOptions.Builder} */ - public CompletionSuggestionBuilder regex(String regex, RegexOptionsBuilder regexOptionsBuilder) { + public CompletionSuggestionBuilder regex(String regex, RegexOptions regexOptions) { this.regex(regex); - this.regexOptionsBuilder = regexOptionsBuilder; + this.regexOptions = regexOptions; return this; } @@ -310,8 +116,8 @@ public class CompletionSuggestionBuilder extends SuggestionBuilder<CompletionSug * Sets the fields to be returned as suggestion payload. * Note: Only doc values enabled fields are supported */ - public CompletionSuggestionBuilder payload(String... fields) { - Collections.addAll(this.payloadFields, fields); + public CompletionSuggestionBuilder payload(List<String> fields) { + this.payloadFields.addAll(fields); return this; } @@ -333,8 +139,8 @@ public class CompletionSuggestionBuilder extends SuggestionBuilder<CompletionSug return contexts(name, queryContexts); } - private CompletionSuggestionBuilder contexts(String name, ToXContent... queryContexts) { - List<ToXContent> contexts = this.queryContexts.get(name); + private CompletionSuggestionBuilder contexts(String name, QueryContext... queryContexts) { + List<QueryContext> contexts = this.queryContexts.get(name); if (contexts == null) { contexts = new ArrayList<>(2); this.queryContexts.put(name, contexts); @@ -345,22 +151,22 @@ public class CompletionSuggestionBuilder extends SuggestionBuilder<CompletionSug @Override protected XContentBuilder innerToXContent(XContentBuilder builder, Params params) throws IOException { - if (payloadFields != null) { + if (payloadFields.isEmpty() == false) { builder.startArray(PAYLOAD_FIELD.getPreferredName()); for (String field : payloadFields) { builder.value(field); } builder.endArray(); } - if (fuzzyOptionsBuilder != null) { - fuzzyOptionsBuilder.toXContent(builder, params); + if (fuzzyOptions != null) { + fuzzyOptions.toXContent(builder, params); } - if (regexOptionsBuilder != null) { - regexOptionsBuilder.toXContent(builder, params); + if (regexOptions != null) { + regexOptions.toXContent(builder, params); } if (queryContexts.isEmpty() == false) { builder.startObject(CONTEXTS_FIELD.getPreferredName()); - for (Map.Entry<String, List<ToXContent>> entry : this.queryContexts.entrySet()) { + for (Map.Entry<String, List<QueryContext>> entry : this.queryContexts.entrySet()) { builder.startArray(entry.getKey()); for (ToXContent queryContext : entry.getValue()) { queryContext.toXContent(builder, params); @@ -374,8 +180,8 @@ public class CompletionSuggestionBuilder extends SuggestionBuilder<CompletionSug @Override protected CompletionSuggestionBuilder innerFromXContent(QueryParseContext parseContext, String name) throws IOException { - // NORELEASE - return new CompletionSuggestionBuilder(name); + // NORELEASE implement parsing logic + throw new UnsupportedOperationException(); } @Override @@ -391,25 +197,77 @@ public class CompletionSuggestionBuilder extends SuggestionBuilder<CompletionSug @Override public void doWriteTo(StreamOutput out) throws IOException { - // NORELEASE - throw new UnsupportedOperationException(); + boolean payloadFieldExists = payloadFields.isEmpty() == false; + out.writeBoolean(payloadFieldExists); + if (payloadFieldExists) { + 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); + } + boolean queryContextsExists = queryContexts.isEmpty() == false; + out.writeBoolean(queryContextsExists); + if (queryContextsExists) { + out.writeVInt(queryContexts.size()); + for (Map.Entry<String, List<QueryContext>> namedQueryContexts : queryContexts.entrySet()) { + out.writeString(namedQueryContexts.getKey()); + List<QueryContext> queryContexts = namedQueryContexts.getValue(); + out.writeVInt(queryContexts.size()); + for (QueryContext queryContext : queryContexts) { + out.writeCompletionSuggestionQueryContext(queryContext); + } + } + } } @Override public CompletionSuggestionBuilder doReadFrom(StreamInput in, String name) throws IOException { - // NORELEASE - throw new UnsupportedOperationException(); + CompletionSuggestionBuilder completionSuggestionBuilder = new CompletionSuggestionBuilder(name); + if (in.readBoolean()) { + int numPayloadField = in.readVInt(); + for (int i = 0; i < numPayloadField; i++) { + completionSuggestionBuilder.payloadFields.add(in.readString()); + } + } + if (in.readBoolean()) { + completionSuggestionBuilder.fuzzyOptions = FuzzyOptions.readFuzzyOptions(in); + } + if (in.readBoolean()) { + completionSuggestionBuilder.regexOptions = RegexOptions.readRegexOptions(in); + } + if (in.readBoolean()) { + int numNamedQueryContexts = in.readVInt(); + for (int i = 0; i < numNamedQueryContexts; i++) { + String queryContextName = in.readString(); + int numQueryContexts = in.readVInt(); + List<QueryContext> queryContexts = new ArrayList<>(numQueryContexts); + for (int j = 0; j < numQueryContexts; j++) { + queryContexts.add(in.readCompletionSuggestionQueryContext()); + } + completionSuggestionBuilder.queryContexts.put(queryContextName, queryContexts); + } + } + return completionSuggestionBuilder; } @Override protected boolean doEquals(CompletionSuggestionBuilder other) { - // NORELEASE - return false; + return Objects.equals(payloadFields, other.payloadFields) && + Objects.equals(fuzzyOptions, other.fuzzyOptions) && + Objects.equals(regexOptions, other.regexOptions) && + Objects.equals(queryContexts, other.queryContexts); } @Override protected int doHashCode() { - // NORELEASE - return 0; + return Objects.hash(payloadFields, fuzzyOptions, regexOptions, queryContexts); } } |