Merge pull request #16483 from abeyad/feature-term-suggester-xcontent
Feature term suggester xcontent
This commit is contained in:
commit
e82713ae4e
|
@ -265,7 +265,7 @@ public class RestSearchAction extends BaseRestHandler {
|
|||
searchSourceBuilder.suggest(new SuggestBuilder().addSuggestion(
|
||||
termSuggestion(suggestField).field(suggestField)
|
||||
.text(suggestText).size(suggestSize)
|
||||
.suggestMode(SuggestMode.fromString(suggestMode))));
|
||||
.suggestMode(SuggestMode.resolve(suggestMode))));
|
||||
modified = true;
|
||||
}
|
||||
return modified;
|
||||
|
|
|
@ -49,6 +49,7 @@ import org.elasticsearch.index.analysis.ShingleTokenFilterFactory;
|
|||
import org.elasticsearch.index.analysis.TokenFilterFactory;
|
||||
import org.elasticsearch.index.mapper.MapperService;
|
||||
import org.elasticsearch.search.suggest.SuggestionSearchContext.SuggestionContext;
|
||||
import org.elasticsearch.search.suggest.term.TermSuggestionBuilder;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Comparator;
|
||||
|
|
|
@ -19,10 +19,18 @@
|
|||
|
||||
package org.elasticsearch.search.suggest.term;
|
||||
|
||||
import org.apache.lucene.search.spell.DirectSpellChecker;
|
||||
import org.apache.lucene.search.spell.JaroWinklerDistance;
|
||||
import org.apache.lucene.search.spell.LevensteinDistance;
|
||||
import org.apache.lucene.search.spell.LuceneLevenshteinDistance;
|
||||
import org.apache.lucene.search.spell.NGramDistance;
|
||||
import org.apache.lucene.search.spell.StringDistance;
|
||||
import org.elasticsearch.common.ParseFieldMatcher;
|
||||
import org.elasticsearch.common.io.stream.StreamInput;
|
||||
import org.elasticsearch.common.io.stream.StreamOutput;
|
||||
import org.elasticsearch.common.io.stream.Writeable;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.index.query.QueryParseContext;
|
||||
import org.elasticsearch.search.suggest.SuggestionBuilder;
|
||||
|
||||
|
@ -37,6 +45,16 @@ import static org.elasticsearch.search.suggest.DirectSpellcheckerSettings.DEFAUL
|
|||
import static org.elasticsearch.search.suggest.DirectSpellcheckerSettings.DEFAULT_MIN_DOC_FREQ;
|
||||
import static org.elasticsearch.search.suggest.DirectSpellcheckerSettings.DEFAULT_MIN_WORD_LENGTH;
|
||||
import static org.elasticsearch.search.suggest.DirectSpellcheckerSettings.DEFAULT_PREFIX_LENGTH;
|
||||
import static org.elasticsearch.search.suggest.SuggestUtils.Fields.ACCURACY;
|
||||
import static org.elasticsearch.search.suggest.SuggestUtils.Fields.MAX_EDITS;
|
||||
import static org.elasticsearch.search.suggest.SuggestUtils.Fields.MAX_INSPECTIONS;
|
||||
import static org.elasticsearch.search.suggest.SuggestUtils.Fields.MAX_TERM_FREQ;
|
||||
import static org.elasticsearch.search.suggest.SuggestUtils.Fields.MIN_DOC_FREQ;
|
||||
import static org.elasticsearch.search.suggest.SuggestUtils.Fields.MIN_WORD_LENGTH;
|
||||
import static org.elasticsearch.search.suggest.SuggestUtils.Fields.PREFIX_LENGTH;
|
||||
import static org.elasticsearch.search.suggest.SuggestUtils.Fields.SORT;
|
||||
import static org.elasticsearch.search.suggest.SuggestUtils.Fields.STRING_DISTANCE;
|
||||
import static org.elasticsearch.search.suggest.SuggestUtils.Fields.SUGGEST_MODE;
|
||||
|
||||
/**
|
||||
* Defines the actual suggest command. Each command uses the global options
|
||||
|
@ -309,42 +327,64 @@ public class TermSuggestionBuilder extends SuggestionBuilder<TermSuggestionBuild
|
|||
|
||||
@Override
|
||||
public XContentBuilder innerToXContent(XContentBuilder builder, Params params) throws IOException {
|
||||
if (suggestMode != null) {
|
||||
builder.field("suggest_mode", suggestMode);
|
||||
}
|
||||
if (accuracy != null) {
|
||||
builder.field("accuracy", accuracy);
|
||||
}
|
||||
if (sort != null) {
|
||||
builder.field("sort", sort);
|
||||
}
|
||||
if (stringDistance != null) {
|
||||
builder.field("string_distance", stringDistance);
|
||||
}
|
||||
if (maxEdits != null) {
|
||||
builder.field("max_edits", maxEdits);
|
||||
}
|
||||
if (maxInspections != null) {
|
||||
builder.field("max_inspections", maxInspections);
|
||||
}
|
||||
if (maxTermFreq != null) {
|
||||
builder.field("max_term_freq", maxTermFreq);
|
||||
}
|
||||
if (prefixLength != null) {
|
||||
builder.field("prefix_length", prefixLength);
|
||||
}
|
||||
if (minWordLength != null) {
|
||||
builder.field("min_word_length", minWordLength);
|
||||
}
|
||||
if (minDocFreq != null) {
|
||||
builder.field("min_doc_freq", minDocFreq);
|
||||
}
|
||||
builder.field(SUGGEST_MODE.getPreferredName(), suggestMode);
|
||||
builder.field(ACCURACY.getPreferredName(), accuracy);
|
||||
builder.field(SORT.getPreferredName(), sort);
|
||||
builder.field(STRING_DISTANCE.getPreferredName(), stringDistance);
|
||||
builder.field(MAX_EDITS.getPreferredName(), maxEdits);
|
||||
builder.field(MAX_INSPECTIONS.getPreferredName(), maxInspections);
|
||||
builder.field(MAX_TERM_FREQ.getPreferredName(), maxTermFreq);
|
||||
builder.field(PREFIX_LENGTH.getPreferredName(), prefixLength);
|
||||
builder.field(MIN_WORD_LENGTH.getPreferredName(), minWordLength);
|
||||
builder.field(MIN_DOC_FREQ.getPreferredName(), minDocFreq);
|
||||
return builder;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected TermSuggestionBuilder innerFromXContent(QueryParseContext parseContext, String name) throws IOException {
|
||||
return null;
|
||||
XContentParser parser = parseContext.parser();
|
||||
TermSuggestionBuilder suggestion = new TermSuggestionBuilder(name);
|
||||
ParseFieldMatcher parseFieldMatcher = parseContext.parseFieldMatcher();
|
||||
XContentParser.Token token;
|
||||
String fieldName = null;
|
||||
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
|
||||
if (token == XContentParser.Token.FIELD_NAME) {
|
||||
fieldName = parser.currentName();
|
||||
} else if (token.isValue()) {
|
||||
if (parseFieldMatcher.match(fieldName, SuggestionBuilder.ANALYZER_FIELD)) {
|
||||
suggestion.analyzer(parser.text());
|
||||
} else if (parseFieldMatcher.match(fieldName, SuggestionBuilder.FIELDNAME_FIELD)) {
|
||||
suggestion.field(parser.text());
|
||||
} else if (parseFieldMatcher.match(fieldName, SuggestionBuilder.SIZE_FIELD)) {
|
||||
suggestion.size(parser.intValue());
|
||||
} else if (parseFieldMatcher.match(fieldName, SuggestionBuilder.SHARDSIZE_FIELD)) {
|
||||
suggestion.shardSize(parser.intValue());
|
||||
} else if (parseFieldMatcher.match(fieldName, SUGGEST_MODE)) {
|
||||
suggestion.suggestMode(SuggestMode.resolve(parser.text()));
|
||||
} else if (parseFieldMatcher.match(fieldName, ACCURACY)) {
|
||||
suggestion.accuracy(parser.floatValue());
|
||||
} else if (parseFieldMatcher.match(fieldName, SORT)) {
|
||||
suggestion.sort(SortBy.resolve(parser.text()));
|
||||
} else if (parseFieldMatcher.match(fieldName, STRING_DISTANCE)) {
|
||||
suggestion.stringDistance(StringDistanceImpl.resolve(parser.text()));
|
||||
} else if (parseFieldMatcher.match(fieldName, MAX_EDITS)) {
|
||||
suggestion.maxEdits(parser.intValue());
|
||||
} else if (parseFieldMatcher.match(fieldName, MAX_INSPECTIONS)) {
|
||||
suggestion.maxInspections(parser.intValue());
|
||||
} else if (parseFieldMatcher.match(fieldName, MAX_TERM_FREQ)) {
|
||||
suggestion.maxTermFreq(parser.floatValue());
|
||||
} else if (parseFieldMatcher.match(fieldName, PREFIX_LENGTH)) {
|
||||
suggestion.prefixLength(parser.intValue());
|
||||
} else if (parseFieldMatcher.match(fieldName, MIN_WORD_LENGTH)) {
|
||||
suggestion.minWordLength(parser.intValue());
|
||||
} else if (parseFieldMatcher.match(fieldName, MIN_DOC_FREQ)) {
|
||||
suggestion.minDocFreq(parser.floatValue());
|
||||
}
|
||||
} else {
|
||||
throw new IllegalArgumentException("suggester[term] doesn't support field [" + fieldName + "]");
|
||||
}
|
||||
}
|
||||
return suggestion;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -402,7 +442,6 @@ public class TermSuggestionBuilder extends SuggestionBuilder<TermSuggestionBuild
|
|||
maxTermFreq, prefixLength, minWordLength, minDocFreq);
|
||||
}
|
||||
|
||||
|
||||
/** An enum representing the valid suggest modes. */
|
||||
public enum SuggestMode implements Writeable<SuggestMode> {
|
||||
/** Only suggest terms in the suggest text that aren't in the index. This is the default. */
|
||||
|
@ -428,7 +467,7 @@ public class TermSuggestionBuilder extends SuggestionBuilder<TermSuggestionBuild
|
|||
return values()[ordinal];
|
||||
}
|
||||
|
||||
public static SuggestMode fromString(final String str) {
|
||||
public static SuggestMode resolve(final String str) {
|
||||
Objects.requireNonNull(str, "Input string is null");
|
||||
return valueOf(str.toUpperCase(Locale.ROOT));
|
||||
}
|
||||
|
@ -457,7 +496,7 @@ public class TermSuggestionBuilder extends SuggestionBuilder<TermSuggestionBuild
|
|||
return values()[ordinal];
|
||||
}
|
||||
|
||||
public static SortBy fromString(final String str) {
|
||||
public static SortBy resolve(final String str) {
|
||||
Objects.requireNonNull(str, "Input string is null");
|
||||
return valueOf(str.toUpperCase(Locale.ROOT));
|
||||
}
|
||||
|
@ -493,9 +532,21 @@ public class TermSuggestionBuilder extends SuggestionBuilder<TermSuggestionBuild
|
|||
return values()[ordinal];
|
||||
}
|
||||
|
||||
public static StringDistanceImpl fromString(final String str) {
|
||||
public static StringDistanceImpl resolve(final String str) {
|
||||
Objects.requireNonNull(str, "Input string is null");
|
||||
return valueOf(str.toUpperCase(Locale.ROOT));
|
||||
final String distanceVal = str.toLowerCase(Locale.US);
|
||||
switch (distanceVal) {
|
||||
case "internal":
|
||||
return INTERNAL;
|
||||
case "damerau_levenshtein":
|
||||
case "damerauLevenshtein":
|
||||
return DAMERAU_LEVENSHTEIN;
|
||||
case "levenstein":
|
||||
return LEVENSTEIN;
|
||||
case "ngram":
|
||||
return NGRAM;
|
||||
default: throw new IllegalArgumentException("Illegal distance option " + str);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -39,17 +39,17 @@ public class SortByTests extends AbstractWriteableEnumTestCase {
|
|||
|
||||
@Override
|
||||
public void testFromString() {
|
||||
assertThat(SortBy.fromString("score"), equalTo(SortBy.SCORE));
|
||||
assertThat(SortBy.fromString("frequency"), equalTo(SortBy.FREQUENCY));
|
||||
assertThat(SortBy.resolve("score"), equalTo(SortBy.SCORE));
|
||||
assertThat(SortBy.resolve("frequency"), equalTo(SortBy.FREQUENCY));
|
||||
final String doesntExist = "doesnt_exist";
|
||||
try {
|
||||
SortBy.fromString(doesntExist);
|
||||
SortBy.resolve(doesntExist);
|
||||
fail("SortBy should not have an element " + doesntExist);
|
||||
} catch (IllegalArgumentException e) {
|
||||
}
|
||||
try {
|
||||
SortBy.fromString(null);
|
||||
fail("SortBy.fromString on a null value should throw an exception.");
|
||||
SortBy.resolve(null);
|
||||
fail("SortBy.resolve on a null value should throw an exception.");
|
||||
} catch (NullPointerException e) {
|
||||
assertThat(e.getMessage(), equalTo("Input string is null"));
|
||||
}
|
||||
|
|
|
@ -42,20 +42,20 @@ public class StringDistanceImplTests extends AbstractWriteableEnumTestCase {
|
|||
|
||||
@Override
|
||||
public void testFromString() {
|
||||
assertThat(StringDistanceImpl.fromString("internal"), equalTo(StringDistanceImpl.INTERNAL));
|
||||
assertThat(StringDistanceImpl.fromString("damerau_levenshtein"), equalTo(StringDistanceImpl.DAMERAU_LEVENSHTEIN));
|
||||
assertThat(StringDistanceImpl.fromString("levenstein"), equalTo(StringDistanceImpl.LEVENSTEIN));
|
||||
assertThat(StringDistanceImpl.fromString("jarowinkler"), equalTo(StringDistanceImpl.JAROWINKLER));
|
||||
assertThat(StringDistanceImpl.fromString("ngram"), equalTo(StringDistanceImpl.NGRAM));
|
||||
assertThat(StringDistanceImpl.resolve("internal"), equalTo(StringDistanceImpl.INTERNAL));
|
||||
assertThat(StringDistanceImpl.resolve("damerau_levenshtein"), equalTo(StringDistanceImpl.DAMERAU_LEVENSHTEIN));
|
||||
assertThat(StringDistanceImpl.resolve("levenstein"), equalTo(StringDistanceImpl.LEVENSTEIN));
|
||||
assertThat(StringDistanceImpl.resolve("jarowinkler"), equalTo(StringDistanceImpl.JAROWINKLER));
|
||||
assertThat(StringDistanceImpl.resolve("ngram"), equalTo(StringDistanceImpl.NGRAM));
|
||||
final String doesntExist = "doesnt_exist";
|
||||
try {
|
||||
StringDistanceImpl.fromString(doesntExist);
|
||||
StringDistanceImpl.resolve(doesntExist);
|
||||
fail("StringDistanceImpl should not have an element " + doesntExist);
|
||||
} catch (IllegalArgumentException e) {
|
||||
}
|
||||
try {
|
||||
StringDistanceImpl.fromString(null);
|
||||
fail("StringDistanceImpl.fromString on a null value should throw an exception.");
|
||||
StringDistanceImpl.resolve(null);
|
||||
fail("StringDistanceImpl.resolve on a null value should throw an exception.");
|
||||
} catch (NullPointerException e) {
|
||||
assertThat(e.getMessage(), equalTo("Input string is null"));
|
||||
}
|
||||
|
|
|
@ -40,18 +40,18 @@ public class SuggestModeTests extends AbstractWriteableEnumTestCase {
|
|||
|
||||
@Override
|
||||
public void testFromString() {
|
||||
assertThat(SuggestMode.fromString("missing"), equalTo(SuggestMode.MISSING));
|
||||
assertThat(SuggestMode.fromString("popular"), equalTo(SuggestMode.POPULAR));
|
||||
assertThat(SuggestMode.fromString("always"), equalTo(SuggestMode.ALWAYS));
|
||||
assertThat(SuggestMode.resolve("missing"), equalTo(SuggestMode.MISSING));
|
||||
assertThat(SuggestMode.resolve("popular"), equalTo(SuggestMode.POPULAR));
|
||||
assertThat(SuggestMode.resolve("always"), equalTo(SuggestMode.ALWAYS));
|
||||
final String doesntExist = "doesnt_exist";
|
||||
try {
|
||||
SuggestMode.fromString(doesntExist);
|
||||
SuggestMode.resolve(doesntExist);
|
||||
fail("SuggestMode should not have an element " + doesntExist);
|
||||
} catch (IllegalArgumentException e) {
|
||||
}
|
||||
try {
|
||||
SuggestMode.fromString(null);
|
||||
fail("SuggestMode.fromString on a null value should throw an exception.");
|
||||
SuggestMode.resolve(null);
|
||||
fail("SuggestMode.resolve on a null value should throw an exception.");
|
||||
} catch (NullPointerException e) {
|
||||
assertThat(e.getMessage(), equalTo("Input string is null"));
|
||||
}
|
||||
|
|
|
@ -33,14 +33,6 @@ import static org.hamcrest.Matchers.notNullValue;
|
|||
*/
|
||||
public class TermSuggestionBuilderTests extends AbstractSuggestionBuilderTestCase<TermSuggestionBuilder> {
|
||||
|
||||
/**
|
||||
* creates random suggestion builder, renders it to xContent and back to new instance that should be equal to original
|
||||
*/
|
||||
@Override
|
||||
public void testFromXContent() throws IOException {
|
||||
// skip for now
|
||||
}
|
||||
|
||||
@Override
|
||||
protected TermSuggestionBuilder randomSuggestionBuilder() {
|
||||
TermSuggestionBuilder testBuilder = new TermSuggestionBuilder(randomAsciiOfLength(10));
|
||||
|
|
Loading…
Reference in New Issue