summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristoph Büscher <christoph@elastic.co>2017-02-20 15:45:10 +0100
committerGitHub <noreply@github.com>2017-02-20 15:45:10 +0100
commitea7deace5dd3c293dadb508979511c28d785588d (patch)
tree38f93d28c765169014cb6e458edd4bf00d157e3d
parentea9d51114c6da056fb3b1bae6a6ece4d29edf922 (diff)
Adding fromXContent to Suggest and Suggestion class (#23226)
A follow up to #23202, this adds parsing from xContent and tests to the four Suggestion implementations and the top level suggest element to be used later when parsing the entire SearchResponse.
-rw-r--r--core/src/main/java/org/elasticsearch/common/xcontent/XContentHelper.java10
-rw-r--r--core/src/main/java/org/elasticsearch/search/suggest/Suggest.java67
-rw-r--r--core/src/main/java/org/elasticsearch/search/suggest/completion/CompletionSuggestion.java2
-rw-r--r--core/src/main/java/org/elasticsearch/search/suggest/phrase/PhraseSuggestion.java2
-rw-r--r--core/src/main/java/org/elasticsearch/search/suggest/term/TermSuggestion.java2
-rw-r--r--core/src/test/java/org/elasticsearch/search/suggest/SuggestTests.java72
-rw-r--r--core/src/test/java/org/elasticsearch/search/suggest/SuggestionTests.java240
7 files changed, 388 insertions, 7 deletions
diff --git a/core/src/main/java/org/elasticsearch/common/xcontent/XContentHelper.java b/core/src/main/java/org/elasticsearch/common/xcontent/XContentHelper.java
index 968ad8ac6b..0c6cb1c5cd 100644
--- a/core/src/main/java/org/elasticsearch/common/xcontent/XContentHelper.java
+++ b/core/src/main/java/org/elasticsearch/common/xcontent/XContentHelper.java
@@ -448,12 +448,20 @@ public class XContentHelper {
* {@link XContentType}. Wraps the output into a new anonymous object.
*/
public static BytesReference toXContent(ToXContent toXContent, XContentType xContentType, boolean humanReadable) throws IOException {
+ return toXContent(toXContent, xContentType, ToXContent.EMPTY_PARAMS, humanReadable);
+ }
+
+ /**
+ * Returns the bytes that represent the XContent output of the provided {@link ToXContent} object, using the provided
+ * {@link XContentType}. Wraps the output into a new anonymous object.
+ */
+ public static BytesReference toXContent(ToXContent toXContent, XContentType xContentType, Params params, boolean humanReadable) throws IOException {
try (XContentBuilder builder = XContentBuilder.builder(xContentType.xContent())) {
builder.humanReadable(humanReadable);
if (toXContent.isFragment()) {
builder.startObject();
}
- toXContent.toXContent(builder, ToXContent.EMPTY_PARAMS);
+ toXContent.toXContent(builder, params);
if (toXContent.isFragment()) {
builder.endObject();
}
diff --git a/core/src/main/java/org/elasticsearch/search/suggest/Suggest.java b/core/src/main/java/org/elasticsearch/search/suggest/Suggest.java
index 36a780fec3..ba5ad712f4 100644
--- a/core/src/main/java/org/elasticsearch/search/suggest/Suggest.java
+++ b/core/src/main/java/org/elasticsearch/search/suggest/Suggest.java
@@ -20,6 +20,7 @@ package org.elasticsearch.search.suggest;
import org.apache.lucene.util.CollectionUtil;
import org.elasticsearch.common.ParseField;
+import org.elasticsearch.common.ParsingException;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.io.stream.Streamable;
@@ -47,17 +48,19 @@ import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
+import java.util.function.Function;
import java.util.stream.Collectors;
import static org.elasticsearch.common.xcontent.ConstructingObjectParser.constructorArg;
import static org.elasticsearch.common.xcontent.ConstructingObjectParser.optionalConstructorArg;
+import static org.elasticsearch.common.xcontent.XContentParserUtils.ensureExpectedToken;
/**
* Top level suggest result, containing the result for each suggestion.
*/
public class Suggest implements Iterable<Suggest.Suggestion<? extends Entry<? extends Option>>>, Streamable, ToXContent {
- private static final String NAME = "suggest";
+ static final String NAME = "suggest";
public static final Comparator<Option> COMPARATOR = (first, second) -> {
int cmp = Float.compare(second.getScore(), first.getScore());
@@ -72,7 +75,7 @@ public class Suggest implements Iterable<Suggest.Suggestion<? extends Entry<? ex
private Map<String, Suggestion<? extends Entry<? extends Option>>> suggestMap;
- public Suggest() {
+ private Suggest() {
this(Collections.emptyList());
}
@@ -167,6 +170,18 @@ public class Suggest implements Iterable<Suggest.Suggestion<? extends Entry<? ex
return builder;
}
+ /**
+ * this parsing method assumes that the leading "suggest" field name has already been parsed by the caller
+ */
+ public static Suggest fromXContent(XContentParser parser) throws IOException {
+ ensureExpectedToken(XContentParser.Token.START_OBJECT, parser.currentToken(), parser::getTokenLocation);
+ List<Suggestion<? extends Entry<? extends Option>>> suggestions = new ArrayList<>();
+ while ((parser.nextToken()) != XContentParser.Token.END_OBJECT) {
+ suggestions.add(Suggestion.fromXContent(parser));
+ }
+ return new Suggest(suggestions);
+ }
+
public static Suggest readSuggest(StreamInput in) throws IOException {
Suggest result = new Suggest();
result.readFrom(in);
@@ -216,7 +231,7 @@ public class Suggest implements Iterable<Suggest.Suggestion<? extends Entry<? ex
protected int size;
protected final List<T> entries = new ArrayList<>(5);
- public Suggestion() {
+ protected Suggestion() {
}
public Suggestion(String name, int size) {
@@ -369,6 +384,52 @@ public class Suggest implements Iterable<Suggest.Suggestion<? extends Entry<? ex
return builder;
}
+ public static Suggestion<? extends Entry<? extends Option>> fromXContent(XContentParser parser) throws IOException {
+ ensureExpectedToken(XContentParser.Token.FIELD_NAME, parser.currentToken(), parser::getTokenLocation);
+ String typeAndName = parser.currentName();
+ // we need to extract the type prefix from the name and throw error if it is not present
+ int delimiterPos = typeAndName.indexOf(InternalAggregation.TYPED_KEYS_DELIMITER);
+ String type = null;
+ String name = null;
+ if (delimiterPos > 0) {
+ type = typeAndName.substring(0, delimiterPos);
+ name = typeAndName.substring(delimiterPos + 1);
+ } else {
+ throw new ParsingException(parser.getTokenLocation(),
+ "Cannot parse suggestion response without type information. Set [" + RestSearchAction.TYPED_KEYS_PARAM
+ + "] parameter on the request to ensure the type information is added to the response output");
+ }
+ Suggestion suggestion = null;
+ Function<XContentParser, Entry> entryParser = null;
+ // the "size" parameter and the SortBy for TermSuggestion cannot be parsed from the response, use default values
+ // TODO investigate if we can use NamedXContentRegistry instead of this switch
+ switch (type) {
+ case Suggestion.NAME:
+ suggestion = new Suggestion(name, -1);
+ entryParser = Suggestion.Entry::fromXContent;
+ break;
+ case PhraseSuggestion.NAME:
+ suggestion = new PhraseSuggestion(name, -1);
+ entryParser = PhraseSuggestion.Entry::fromXContent;
+ break;
+ case TermSuggestion.NAME:
+ suggestion = new TermSuggestion(name, -1, SortBy.SCORE);
+ entryParser = TermSuggestion.Entry::fromXContent;
+ break;
+ case CompletionSuggestion.NAME:
+ suggestion = new CompletionSuggestion(name, -1);
+ entryParser = CompletionSuggestion.Entry::fromXContent;
+ break;
+ default:
+ throw new ParsingException(parser.getTokenLocation(), "Unknown suggestion type [{}]", type);
+ }
+ ensureExpectedToken(XContentParser.Token.START_ARRAY, parser.nextToken(), parser::getTokenLocation);
+ while ((parser.nextToken()) != XContentParser.Token.END_ARRAY) {
+ suggestion.addTerm(entryParser.apply(parser));
+ }
+ return suggestion;
+ }
+
/**
* Represents a part from the suggest text with suggested options.
*/
diff --git a/core/src/main/java/org/elasticsearch/search/suggest/completion/CompletionSuggestion.java b/core/src/main/java/org/elasticsearch/search/suggest/completion/CompletionSuggestion.java
index 51b44a300d..ed45104d99 100644
--- a/core/src/main/java/org/elasticsearch/search/suggest/completion/CompletionSuggestion.java
+++ b/core/src/main/java/org/elasticsearch/search/suggest/completion/CompletionSuggestion.java
@@ -64,7 +64,7 @@ import static org.elasticsearch.search.suggest.Suggest.COMPARATOR;
*/
public final class CompletionSuggestion extends Suggest.Suggestion<CompletionSuggestion.Entry> {
- private static final String NAME = "completion";
+ public static final String NAME = "completion";
public static final int TYPE = 4;
diff --git a/core/src/main/java/org/elasticsearch/search/suggest/phrase/PhraseSuggestion.java b/core/src/main/java/org/elasticsearch/search/suggest/phrase/PhraseSuggestion.java
index 3ea0d61d72..fb646b03ae 100644
--- a/core/src/main/java/org/elasticsearch/search/suggest/phrase/PhraseSuggestion.java
+++ b/core/src/main/java/org/elasticsearch/search/suggest/phrase/PhraseSuggestion.java
@@ -35,7 +35,7 @@ import java.io.IOException;
*/
public class PhraseSuggestion extends Suggest.Suggestion<PhraseSuggestion.Entry> {
- private static final String NAME = "phrase";
+ public static final String NAME = "phrase";
public static final int TYPE = 3;
public PhraseSuggestion() {
diff --git a/core/src/main/java/org/elasticsearch/search/suggest/term/TermSuggestion.java b/core/src/main/java/org/elasticsearch/search/suggest/term/TermSuggestion.java
index 5f6cd310ad..31621fb63b 100644
--- a/core/src/main/java/org/elasticsearch/search/suggest/term/TermSuggestion.java
+++ b/core/src/main/java/org/elasticsearch/search/suggest/term/TermSuggestion.java
@@ -41,7 +41,7 @@ import static org.elasticsearch.common.xcontent.ConstructingObjectParser.constru
*/
public class TermSuggestion extends Suggestion<TermSuggestion.Entry> {
- private static final String NAME = "term";
+ public static final String NAME = "term";
public static final Comparator<Suggestion.Entry.Option> SCORE = new Score();
public static final Comparator<Suggestion.Entry.Option> FREQUENCY = new Frequency();
diff --git a/core/src/test/java/org/elasticsearch/search/suggest/SuggestTests.java b/core/src/test/java/org/elasticsearch/search/suggest/SuggestTests.java
index bed6d5997d..0948b9e2ff 100644
--- a/core/src/test/java/org/elasticsearch/search/suggest/SuggestTests.java
+++ b/core/src/test/java/org/elasticsearch/search/suggest/SuggestTests.java
@@ -19,20 +19,92 @@
package org.elasticsearch.search.suggest;
+import org.elasticsearch.common.bytes.BytesReference;
+import org.elasticsearch.common.text.Text;
+import org.elasticsearch.common.xcontent.ToXContent;
+import org.elasticsearch.common.xcontent.XContentParser;
+import org.elasticsearch.common.xcontent.XContentType;
+import org.elasticsearch.rest.action.search.RestSearchAction;
+import org.elasticsearch.search.suggest.Suggest.Suggestion;
+import org.elasticsearch.search.suggest.Suggest.Suggestion.Entry;
+import org.elasticsearch.search.suggest.Suggest.Suggestion.Entry.Option;
import org.elasticsearch.search.suggest.completion.CompletionSuggestion;
import org.elasticsearch.search.suggest.phrase.PhraseSuggestion;
import org.elasticsearch.search.suggest.term.TermSuggestion;
import org.elasticsearch.test.ESTestCase;
+import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
+import static org.elasticsearch.common.xcontent.XContentHelper.toXContent;
+import static org.elasticsearch.common.xcontent.XContentParserUtils.ensureExpectedToken;
+import static org.elasticsearch.common.xcontent.XContentParserUtils.ensureFieldName;
+import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertToXContentEquivalent;
import static org.hamcrest.Matchers.equalTo;
public class SuggestTests extends ESTestCase {
+ public static Suggest createTestItem() {
+ int numEntries = randomIntBetween(0, 5);
+ List<Suggestion<? extends Entry<? extends Option>>> suggestions = new ArrayList<>();
+ for (int i = 0; i < numEntries; i++) {
+ suggestions.add(SuggestionTests.createTestItem());
+ }
+ return new Suggest(suggestions);
+ }
+
+ public void testFromXContent() throws IOException {
+ ToXContent.Params params = new ToXContent.MapParams(Collections.singletonMap(RestSearchAction.TYPED_KEYS_PARAM, "true"));
+ Suggest suggest = createTestItem();
+ XContentType xContentType = randomFrom(XContentType.values());
+ boolean humanReadable = randomBoolean();
+ BytesReference originalBytes = toXContent(suggest, xContentType, params, humanReadable);
+ Suggest parsed;
+ try (XContentParser parser = createParser(xContentType.xContent(), originalBytes)) {
+ ensureExpectedToken(XContentParser.Token.START_OBJECT, parser.nextToken(), parser::getTokenLocation);
+ ensureFieldName(parser, parser.nextToken(), Suggest.NAME);
+ ensureExpectedToken(XContentParser.Token.START_OBJECT, parser.nextToken(), parser::getTokenLocation);
+ parsed = Suggest.fromXContent(parser);
+ assertEquals(XContentParser.Token.END_OBJECT, parser.currentToken());
+ assertEquals(XContentParser.Token.END_OBJECT, parser.nextToken());
+ assertNull(parser.nextToken());
+ }
+ assertEquals(suggest.size(), parsed.size());
+ for (Suggestion suggestion : suggest) {
+ Suggestion<? extends Entry<? extends Option>> parsedSuggestion = parsed.getSuggestion(suggestion.getName());
+ assertNotNull(parsedSuggestion);
+ assertEquals(suggestion.getClass(), parsedSuggestion.getClass());
+ }
+ assertToXContentEquivalent(originalBytes, toXContent(parsed, xContentType, params, humanReadable), xContentType);
+ }
+
+ public void testToXContent() throws IOException {
+ Option option = new Option(new Text("someText"), new Text("somethingHighlighted"), 1.3f, true);
+ Entry<Option> entry = new Entry<>(new Text("entryText"), 42, 313);
+ entry.addOption(option);
+ Suggestion<Entry<Option>> suggestion = new Suggestion<>("suggestionName", 5);
+ suggestion.addTerm(entry);
+ Suggest suggest = new Suggest(Collections.singletonList(suggestion));
+ BytesReference xContent = toXContent(suggest, XContentType.JSON, randomBoolean());
+ assertEquals(
+ "{\"suggest\":"
+ + "{\"suggestionName\":"
+ + "[{\"text\":\"entryText\","
+ + "\"offset\":42,"
+ + "\"length\":313,"
+ + "\"options\":[{\"text\":\"someText\","
+ + "\"highlighted\":\"somethingHighlighted\","
+ + "\"score\":1.3,"
+ + "\"collate_match\":true}]"
+ + "}]"
+ + "}"
+ +"}",
+ xContent.utf8ToString());
+ }
+
public void testFilter() throws Exception {
List<Suggest.Suggestion<? extends Suggest.Suggestion.Entry<? extends Suggest.Suggestion.Entry.Option>>> suggestions;
CompletionSuggestion completionSuggestion = new CompletionSuggestion(randomAsciiOfLength(10), 2);
diff --git a/core/src/test/java/org/elasticsearch/search/suggest/SuggestionTests.java b/core/src/test/java/org/elasticsearch/search/suggest/SuggestionTests.java
new file mode 100644
index 0000000000..e17ead287a
--- /dev/null
+++ b/core/src/test/java/org/elasticsearch/search/suggest/SuggestionTests.java
@@ -0,0 +1,240 @@
+/*
+ * 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;
+
+import org.elasticsearch.common.ParsingException;
+import org.elasticsearch.common.bytes.BytesReference;
+import org.elasticsearch.common.text.Text;
+import org.elasticsearch.common.xcontent.ToXContent;
+import org.elasticsearch.common.xcontent.XContent;
+import org.elasticsearch.common.xcontent.XContentParser;
+import org.elasticsearch.common.xcontent.XContentType;
+import org.elasticsearch.common.xcontent.json.JsonXContent;
+import org.elasticsearch.rest.action.search.RestSearchAction;
+import org.elasticsearch.search.suggest.Suggest.Suggestion;
+import org.elasticsearch.search.suggest.Suggest.Suggestion.Entry;
+import org.elasticsearch.search.suggest.Suggest.Suggestion.Entry.Option;
+import org.elasticsearch.search.suggest.completion.CompletionSuggestion;
+import org.elasticsearch.search.suggest.phrase.PhraseSuggestion;
+import org.elasticsearch.search.suggest.term.TermSuggestion;
+import org.elasticsearch.test.ESTestCase;
+
+import java.io.IOException;
+import java.util.Collections;
+import java.util.Map;
+import java.util.Set;
+import java.util.function.Supplier;
+
+import static org.elasticsearch.common.xcontent.XContentHelper.toXContent;
+import static org.elasticsearch.common.xcontent.XContentParserUtils.ensureExpectedToken;
+import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertToXContentEquivalent;
+
+public class SuggestionTests extends ESTestCase {
+
+ @SuppressWarnings({ "unchecked" })
+ private static final Class<Suggestion<? extends Entry<? extends Option>>>[] SUGGESTION_TYPES = new Class[] {
+ Suggestion.class, TermSuggestion.class, PhraseSuggestion.class, CompletionSuggestion.class
+ };
+
+ public static Suggestion<? extends Entry<? extends Option>> createTestItem() {
+ return createTestItem(randomFrom(SUGGESTION_TYPES));
+ }
+
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ public static Suggestion<? extends Entry<? extends Option>> createTestItem(Class<? extends Suggestion> type) {
+ String name = randomAsciiOfLengthBetween(5, 10);
+ // note: size will not be rendered via "toXContent", only passed on internally on transport layer
+ int size = randomInt();
+ Supplier<Entry> entrySupplier = null;
+ Suggestion suggestion = null;
+ if (type == Suggestion.class) {
+ suggestion = new Suggestion(name, size);
+ entrySupplier = () -> SuggestionEntryTests.createTestItem(Entry.class);
+ } else if (type == TermSuggestion.class) {
+ suggestion = new TermSuggestion(name, size, randomFrom(SortBy.values()));
+ entrySupplier = () -> SuggestionEntryTests.createTestItem(TermSuggestion.Entry.class);
+ } else if (type == PhraseSuggestion.class) {
+ suggestion = new PhraseSuggestion(name, size);
+ entrySupplier = () -> SuggestionEntryTests.createTestItem(PhraseSuggestion.Entry.class);
+ } else if (type == CompletionSuggestion.class) {
+ suggestion = new CompletionSuggestion(name, size);
+ entrySupplier = () -> SuggestionEntryTests.createTestItem(CompletionSuggestion.Entry.class);
+ }
+ int numEntries;
+ if (frequently()) {
+ if (type == CompletionSuggestion.class) {
+ numEntries = 1; // CompletionSuggestion can have max. one entry
+ } else {
+ numEntries = randomIntBetween(1, 5);
+ }
+ } else {
+ numEntries = 0; // also occasionally test zero entries
+ }
+ for (int i = 0; i < numEntries; i++) {
+ suggestion.addTerm(entrySupplier.get());
+ }
+ return suggestion;
+ }
+
+ @SuppressWarnings({ "rawtypes" })
+ public void testFromXContent() throws IOException {
+ ToXContent.Params params = new ToXContent.MapParams(Collections.singletonMap(RestSearchAction.TYPED_KEYS_PARAM, "true"));
+ for (Class<Suggestion<? extends Entry<? extends Option>>> type : SUGGESTION_TYPES) {
+ Suggestion suggestion = createTestItem(type);
+ XContentType xContentType = randomFrom(XContentType.values());
+ boolean humanReadable = randomBoolean();
+ BytesReference originalBytes = toXContent(suggestion, xContentType, params, humanReadable);
+ Suggestion parsed;
+ try (XContentParser parser = createParser(xContentType.xContent(), originalBytes)) {
+ ensureExpectedToken(XContentParser.Token.START_OBJECT, parser.nextToken(), parser::getTokenLocation);
+ ensureExpectedToken(XContentParser.Token.FIELD_NAME, parser.nextToken(), parser::getTokenLocation);
+ parsed = Suggestion.fromXContent(parser);
+ assertEquals(XContentParser.Token.END_OBJECT, parser.nextToken());
+ assertNull(parser.nextToken());
+ }
+ assertEquals(suggestion.getName(), parsed.getName());
+ assertEquals(suggestion.getEntries().size(), parsed.getEntries().size());
+ // We don't parse size via xContent, instead we set it to -1 on the client side
+ assertEquals(-1, parsed.getSize());
+ assertToXContentEquivalent(originalBytes, toXContent(parsed, xContentType, params, humanReadable), xContentType);
+ }
+ }
+
+ /**
+ * test that we throw error if RestSearchAction.TYPED_KEYS_PARAM isn't set while rendering xContent
+ */
+ public void testFromXContentFailsWithoutTypeParam() throws IOException {
+ XContentType xContentType = randomFrom(XContentType.values());
+ BytesReference originalBytes = toXContent(createTestItem(), xContentType, ToXContent.EMPTY_PARAMS, randomBoolean());
+ try (XContentParser parser = createParser(xContentType.xContent(), originalBytes)) {
+ ensureExpectedToken(XContentParser.Token.START_OBJECT, parser.nextToken(), parser::getTokenLocation);
+ ensureExpectedToken(XContentParser.Token.FIELD_NAME, parser.nextToken(), parser::getTokenLocation);
+ ParsingException e = expectThrows(ParsingException.class, () -> Suggestion.fromXContent(parser));
+ assertEquals(
+ "Cannot parse suggestion response without type information. "
+ + "Set [typed_keys] parameter on the request to ensure the type information "
+ + "is added to the response output", e.getMessage());
+ }
+ }
+
+ public void testUnknownSuggestionTypeThrows() throws IOException {
+ XContent xContent = JsonXContent.jsonXContent;
+ String suggestionString =
+ "{\"unknownType#suggestionName\":"
+ + "[{\"text\":\"entryText\","
+ + "\"offset\":42,"
+ + "\"length\":313,"
+ + "\"options\":[{\"text\":\"someText\","
+ + "\"highlighted\":\"somethingHighlighted\","
+ + "\"score\":1.3,"
+ + "\"collate_match\":true}]"
+ + "}]"
+ + "}";
+ try (XContentParser parser = xContent.createParser(xContentRegistry(), suggestionString)) {
+ ensureExpectedToken(XContentParser.Token.START_OBJECT, parser.nextToken(), parser::getTokenLocation);
+ ensureExpectedToken(XContentParser.Token.FIELD_NAME, parser.nextToken(), parser::getTokenLocation);
+ ParsingException e = expectThrows(ParsingException.class, () -> Suggestion.fromXContent(parser));
+ assertEquals("Unknown suggestion type [unknownType]", e.getMessage());
+ }
+ }
+
+ public void testToXContent() throws IOException {
+ ToXContent.Params params = new ToXContent.MapParams(Collections.singletonMap(RestSearchAction.TYPED_KEYS_PARAM, "true"));
+ {
+ Option option = new Option(new Text("someText"), new Text("somethingHighlighted"), 1.3f, true);
+ Entry<Option> entry = new Entry<>(new Text("entryText"), 42, 313);
+ entry.addOption(option);
+ Suggestion<Entry<Option>> suggestion = new Suggestion<>("suggestionName", 5);
+ suggestion.addTerm(entry);
+ BytesReference xContent = toXContent(suggestion, XContentType.JSON, params, randomBoolean());
+ assertEquals(
+ "{\"suggestion#suggestionName\":[{"
+ + "\"text\":\"entryText\","
+ + "\"offset\":42,"
+ + "\"length\":313,"
+ + "\"options\":[{"
+ + "\"text\":\"someText\","
+ + "\"highlighted\":\"somethingHighlighted\","
+ + "\"score\":1.3,"
+ + "\"collate_match\":true}]"
+ + "}]"
+ + "}", xContent.utf8ToString());
+ }
+ {
+ Option option = new Option(new Text("someText"), new Text("somethingHighlighted"), 1.3f, true);
+ PhraseSuggestion.Entry entry = new PhraseSuggestion.Entry(new Text("entryText"), 42, 313, 1.0);
+ entry.addOption(option);
+ PhraseSuggestion suggestion = new PhraseSuggestion("suggestionName", 5);
+ suggestion.addTerm(entry);
+ BytesReference xContent = toXContent(suggestion, XContentType.JSON, params, randomBoolean());
+ assertEquals(
+ "{\"phrase#suggestionName\":[{"
+ + "\"text\":\"entryText\","
+ + "\"offset\":42,"
+ + "\"length\":313,"
+ + "\"options\":[{"
+ + "\"text\":\"someText\","
+ + "\"highlighted\":\"somethingHighlighted\","
+ + "\"score\":1.3,"
+ + "\"collate_match\":true}]"
+ + "}]"
+ + "}", xContent.utf8ToString());
+ }
+ {
+ TermSuggestion.Entry.Option option = new TermSuggestion.Entry.Option(new Text("someText"), 10, 1.3f);
+ TermSuggestion.Entry entry = new TermSuggestion.Entry(new Text("entryText"), 42, 313);
+ entry.addOption(option);
+ TermSuggestion suggestion = new TermSuggestion("suggestionName", 5, SortBy.SCORE);
+ suggestion.addTerm(entry);
+ BytesReference xContent = toXContent(suggestion, XContentType.JSON, params, randomBoolean());
+ assertEquals(
+ "{\"term#suggestionName\":[{"
+ + "\"text\":\"entryText\","
+ + "\"offset\":42,"
+ + "\"length\":313,"
+ + "\"options\":[{"
+ + "\"text\":\"someText\","
+ + "\"score\":1.3,"
+ + "\"freq\":10}]"
+ + "}]"
+ + "}", xContent.utf8ToString());
+ }
+ {
+ Map<String, Set<CharSequence>> contexts = Collections.singletonMap("key", Collections.singleton("value"));
+ CompletionSuggestion.Entry.Option option = new CompletionSuggestion.Entry.Option(1, new Text("someText"), 1.3f, contexts);
+ CompletionSuggestion.Entry entry = new CompletionSuggestion.Entry(new Text("entryText"), 42, 313);
+ entry.addOption(option);
+ CompletionSuggestion suggestion = new CompletionSuggestion("suggestionName", 5);
+ suggestion.addTerm(entry);
+ BytesReference xContent = toXContent(suggestion, XContentType.JSON, params, randomBoolean());
+ assertEquals(
+ "{\"completion#suggestionName\":[{"
+ + "\"text\":\"entryText\","
+ + "\"offset\":42,"
+ + "\"length\":313,"
+ + "\"options\":[{"
+ + "\"text\":\"someText\","
+ + "\"score\":1.3,"
+ + "\"contexts\":{\"key\":[\"value\"]}"
+ + "}]"
+ + "}]}", xContent.utf8ToString());
+ }
+ }
+} \ No newline at end of file