Merge pull request #19877 from areek/fix/remove_completion_payload

Remove payload option from completion suggester
This commit is contained in:
Areek Zillur 2016-08-09 15:27:29 -04:00 committed by GitHub
commit 16d93e5a53
10 changed files with 23 additions and 378 deletions

View File

@ -78,7 +78,6 @@ public class CompletionSuggester extends Suggester<CompletionSuggestionContext>
TopSuggestDocsCollector collector = new TopDocumentsCollector(suggestionContext.getSize());
suggest(searcher, suggestionContext.toQuery(), collector);
int numResult = 0;
List<LeafReaderContext> leaves = searcher.getIndexReader().leaves();
for (TopSuggestDocs.SuggestScoreDoc suggestScoreDoc : collector.get().scoreLookupDocs()) {
TopDocumentsCollector.SuggestDoc suggestDoc = (TopDocumentsCollector.SuggestDoc) suggestScoreDoc;
// collect contexts
@ -86,31 +85,9 @@ public class CompletionSuggester extends Suggester<CompletionSuggestionContext>
if (fieldType.hasContextMappings() && suggestDoc.getContexts().isEmpty() == false) {
contexts = fieldType.getContextMappings().getNamedContexts(suggestDoc.getContexts());
}
// collect payloads
final Map<String, List<Object>> payload = new HashMap<>(0);
List<String> payloadFields = suggestionContext.getPayloadFields();
if (payloadFields.isEmpty() == false) {
final int readerIndex = ReaderUtil.subIndex(suggestDoc.doc, leaves);
final LeafReaderContext subReaderContext = leaves.get(readerIndex);
final int subDocId = suggestDoc.doc - subReaderContext.docBase;
for (String field : payloadFields) {
MapperService mapperService = suggestionContext.getShardContext().getMapperService();
MappedFieldType payloadFieldType = mapperService.fullName(field);
if (payloadFieldType != null) {
QueryShardContext shardContext = suggestionContext.getShardContext();
final AtomicFieldData data = shardContext.getForField(payloadFieldType)
.load(subReaderContext);
final ScriptDocValues scriptValues = data.getScriptValues();
scriptValues.setNextDocId(subDocId);
payload.put(field, new ArrayList<>(scriptValues.getValues()));
} else {
throw new IllegalArgumentException("payload field [" + field + "] does not exist");
}
}
}
if (numResult++ < suggestionContext.getSize()) {
CompletionSuggestion.Entry.Option option = new CompletionSuggestion.Entry.Option(suggestDoc.doc,
new Text(suggestDoc.key.toString()), suggestDoc.score, contexts, payload);
new Text(suggestDoc.key.toString()), suggestDoc.score, contexts);
completionSuggestEntry.addOption(option);
} else {
break;

View File

@ -194,14 +194,12 @@ public final class CompletionSuggestion extends Suggest.Suggestion<CompletionSug
public static class Option extends Suggest.Suggestion.Entry.Option {
private Map<String, Set<CharSequence>> contexts;
private Map<String, List<Object>> payload;
private ScoreDoc doc;
private InternalSearchHit hit;
public Option(int docID, Text text, float score, Map<String, Set<CharSequence>> contexts, Map<String, List<Object>> payload) {
public Option(int docID, Text text, float score, Map<String, Set<CharSequence>> contexts) {
super(text, score);
this.doc = new ScoreDoc(docID, score);
this.payload = payload;
this.contexts = contexts;
}
@ -216,10 +214,6 @@ public final class CompletionSuggestion extends Suggest.Suggestion<CompletionSug
throw new UnsupportedOperationException();
}
public Map<String, List<Object>> getPayload() {
return payload;
}
public Map<String, Set<CharSequence>> getContexts() {
return contexts;
}
@ -248,17 +242,6 @@ public final class CompletionSuggestion extends Suggest.Suggestion<CompletionSug
} else {
builder.field("score", getScore());
}
if (payload.size() > 0) {
builder.startObject("payload");
for (Map.Entry<String, List<Object>> entry : payload.entrySet()) {
builder.startArray(entry.getKey());
for (Object payload : entry.getValue()) {
builder.value(payload);
}
builder.endArray();
}
builder.endObject();
}
if (contexts.size() > 0) {
builder.startObject("contexts");
for (Map.Entry<String, Set<CharSequence>> entry : contexts.entrySet()) {
@ -281,17 +264,6 @@ public final class CompletionSuggestion extends Suggest.Suggestion<CompletionSug
this.hit = InternalSearchHit.readSearchHit(in,
InternalSearchHits.streamContext().streamShardTarget(ShardTargetType.STREAM));
}
int payloadSize = in.readInt();
this.payload = new LinkedHashMap<>(payloadSize);
for (int i = 0; i < payloadSize; i++) {
String payloadName = in.readString();
int nValues = in.readVInt();
List<Object> values = new ArrayList<>(nValues);
for (int j = 0; j < nValues; j++) {
values.add(in.readGenericValue());
}
this.payload.put(payloadName, values);
}
int contextSize = in.readInt();
this.contexts = new LinkedHashMap<>(contextSize);
for (int i = 0; i < contextSize; i++) {
@ -315,15 +287,6 @@ public final class CompletionSuggestion extends Suggest.Suggestion<CompletionSug
} else {
out.writeBoolean(false);
}
out.writeInt(payload.size());
for (Map.Entry<String, List<Object>> entry : payload.entrySet()) {
out.writeString(entry.getKey());
List<Object> values = entry.getValue();
out.writeVInt(values.size());
for (Object value : values) {
out.writeGenericValue(value);
}
}
out.writeInt(contexts.size());
for (Map.Entry<String, Set<CharSequence>> entry : contexts.entrySet()) {
out.writeString(entry.getKey());
@ -341,14 +304,6 @@ public final class CompletionSuggestion extends Suggest.Suggestion<CompletionSug
stringBuilder.append(getText());
stringBuilder.append(" score:");
stringBuilder.append(getScore());
stringBuilder.append(" payload:[");
for (Map.Entry<String, List<Object>> entry : payload.entrySet()) {
stringBuilder.append(" ");
stringBuilder.append(entry.getKey());
stringBuilder.append(":");
stringBuilder.append(entry.getValue());
}
stringBuilder.append("]");
stringBuilder.append(" context:[");
for (Map.Entry<String, Set<CharSequence>> entry: contexts.entrySet()) {
stringBuilder.append(" ");

View File

@ -62,7 +62,6 @@ import java.util.Objects;
*/
public class CompletionSuggestionBuilder extends SuggestionBuilder<CompletionSuggestionBuilder> {
static final String SUGGESTION_NAME = "completion";
static final ParseField PAYLOAD_FIELD = new ParseField("payload");
static final ParseField CONTEXTS_FIELD = new ParseField("contexts", "context");
/**
@ -78,7 +77,6 @@ public class CompletionSuggestionBuilder extends SuggestionBuilder<CompletionSug
private static ObjectParser<CompletionSuggestionBuilder.InnerBuilder, ParseFieldMatcherSupplier> TLP_PARSER =
new ObjectParser<>(SUGGESTION_NAME, null);
static {
TLP_PARSER.declareStringArray(CompletionSuggestionBuilder.InnerBuilder::payload, PAYLOAD_FIELD);
TLP_PARSER.declareField((parser, completionSuggestionContext, context) -> {
if (parser.currentToken() == XContentParser.Token.VALUE_BOOLEAN) {
if (parser.booleanValue()) {
@ -108,7 +106,6 @@ public class CompletionSuggestionBuilder extends SuggestionBuilder<CompletionSug
protected FuzzyOptions fuzzyOptions;
protected RegexOptions regexOptions;
protected BytesReference contextBytes = null;
protected List<String> payloadFields = Collections.emptyList();
public CompletionSuggestionBuilder(String field) {
super(field);
@ -123,7 +120,6 @@ public class CompletionSuggestionBuilder extends SuggestionBuilder<CompletionSug
fuzzyOptions = in.fuzzyOptions;
regexOptions = in.regexOptions;
contextBytes = in.contextBytes;
payloadFields = in.payloadFields;
}
/**
@ -131,8 +127,6 @@ public class CompletionSuggestionBuilder extends SuggestionBuilder<CompletionSug
*/
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();
@ -140,7 +134,6 @@ public class CompletionSuggestionBuilder extends SuggestionBuilder<CompletionSug
@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);
@ -194,16 +187,6 @@ public class CompletionSuggestionBuilder extends SuggestionBuilder<CompletionSug
return this;
}
/**
* Sets the fields to be returned as suggestion payload.
* Note: Only doc values enabled fields are supported
*/
public CompletionSuggestionBuilder payload(List<String> fields) {
Objects.requireNonNull(fields, "payload must not be null");
this.payloadFields = fields;
return this;
}
/**
* Sets query contexts for completion
* @param queryContexts named query contexts
@ -348,13 +331,6 @@ public class CompletionSuggestionBuilder extends SuggestionBuilder<CompletionSug
@Override
protected XContentBuilder innerToXContent(XContentBuilder builder, Params params) throws IOException {
if (payloadFields.isEmpty() == false) {
builder.startArray(PAYLOAD_FIELD.getPreferredName());
for (String field : payloadFields) {
builder.value(field);
}
builder.endArray();
}
if (fuzzyOptions != null) {
fuzzyOptions.toXContent(builder, params);
}
@ -388,7 +364,6 @@ public class CompletionSuggestionBuilder extends SuggestionBuilder<CompletionSug
// copy over common settings to each suggestion builder
final MapperService mapperService = context.getMapperService();
populateCommonFields(mapperService, suggestionContext);
suggestionContext.setPayloadFields(payloadFields);
suggestionContext.setFuzzyOptions(fuzzyOptions);
suggestionContext.setRegexOptions(regexOptions);
MappedFieldType mappedFieldType = mapperService.fullName(suggestionContext.getField());
@ -449,14 +424,13 @@ public class CompletionSuggestionBuilder extends SuggestionBuilder<CompletionSug
@Override
protected boolean doEquals(CompletionSuggestionBuilder other) {
return Objects.equals(payloadFields, other.payloadFields) &&
Objects.equals(fuzzyOptions, other.fuzzyOptions) &&
return Objects.equals(fuzzyOptions, other.fuzzyOptions) &&
Objects.equals(regexOptions, other.regexOptions) &&
Objects.equals(contextBytes, other.contextBytes);
}
@Override
protected int doHashCode() {
return Objects.hash(payloadFields, fuzzyOptions, regexOptions, contextBytes);
return Objects.hash(fuzzyOptions, regexOptions, contextBytes);
}
}

View File

@ -45,7 +45,6 @@ public class CompletionSuggestionContext extends SuggestionSearchContext.Suggest
private FuzzyOptions fuzzyOptions;
private RegexOptions regexOptions;
private Map<String, List<ContextMapping.InternalQueryContext>> queryContexts = Collections.emptyMap();
private List<String> payloadFields = Collections.emptyList();
private CompletionFieldMapper2x.CompletionFieldType fieldType2x;
private List<ContextQuery> contextQueries;
@ -73,14 +72,6 @@ public class CompletionSuggestionContext extends SuggestionSearchContext.Suggest
this.queryContexts = queryContexts;
}
void setPayloadFields(List<String> fields) {
this.payloadFields = fields;
}
List<String> getPayloadFields() {
return payloadFields;
}
public FuzzyOptions getFuzzyOptions() {
return fuzzyOptions;
}

View File

@ -149,7 +149,7 @@ public class SearchPhaseControllerTests extends ESTestCase {
float maxScore = randomIntBetween(suggestion.getSize(), (int) Float.MAX_VALUE);
for (int i = 0; i < optionSize; i++) {
completionEntry.addOption(new CompletionSuggestion.Entry.Option(i, new Text(""), maxScore,
Collections.emptyMap(), Collections.emptyMap()));
Collections.emptyMap()));
float dec = randomIntBetween(0, optionSize);
if (dec <= maxScore) {
maxScore -= dec;

View File

@ -246,156 +246,6 @@ public class CompletionSuggestSearchIT extends ESIntegTestCase {
assertSuggestions("foo", fuzzyPrefix, outputs);
}
public void testSuggestWithNumericPayload() throws Exception {
final CompletionMappingBuilder mapping = new CompletionMappingBuilder();
createIndexAndMapping(mapping);
int numDocs = 10;
List<IndexRequestBuilder> indexRequestBuilders = new ArrayList<>();
for (int i = 0; i < numDocs; i++) {
XContentBuilder source= jsonBuilder()
.startObject()
.field(FIELD, "suggestion" + i)
.field("count", i)
.endObject();
indexRequestBuilders.add(client().prepareIndex(INDEX, TYPE, "" + i).setSource(source));
}
indexRandom(true, indexRequestBuilders);
CompletionSuggestionBuilder prefix = SuggestBuilders.completionSuggestion(FIELD).prefix("sugg").
size(numDocs).payload(Collections.singletonList("count"));
SearchResponse searchResponse = client().prepareSearch(INDEX).suggest(new SuggestBuilder().addSuggestion("foo", prefix))
.execute().actionGet();
assertNoFailures(searchResponse);
CompletionSuggestion completionSuggestion = searchResponse.getSuggest().getSuggestion("foo");
CompletionSuggestion.Entry options = completionSuggestion.getEntries().get(0);
assertThat(options.getOptions().size(), equalTo(numDocs));
for (CompletionSuggestion.Entry.Option option : options) {
Map<String, List<Object>> payloads = option.getPayload();
assertThat(payloads.keySet(), contains("count"));
}
}
public void testMissingPayloadField() throws Exception {
final CompletionMappingBuilder mapping = new CompletionMappingBuilder();
createIndexAndMapping(mapping);
List<IndexRequestBuilder> indexRequestBuilders = Arrays.asList(
client().prepareIndex(INDEX, TYPE, "1").setSource(FIELD, "suggestion", "test_field", "test"),
client().prepareIndex(INDEX, TYPE, "2").setSource(FIELD, "suggestion")
);
indexRandom(true, indexRequestBuilders);
CompletionSuggestionBuilder prefix = SuggestBuilders.completionSuggestion(FIELD).prefix("sugg")
.payload(Collections.singletonList("test_field"));
SearchResponse searchResponse = client().prepareSearch(INDEX).suggest(new SuggestBuilder().addSuggestion("foo", prefix))
.execute().actionGet();
assertNoFailures(searchResponse);
CompletionSuggestion completionSuggestion = searchResponse.getSuggest().getSuggestion("foo");
CompletionSuggestion.Entry options = completionSuggestion.getEntries().get(0);
assertThat(options.getOptions().size(), equalTo(2));
for (CompletionSuggestion.Entry.Option option : options.getOptions()) {
assertThat(option.getPayload().keySet(), contains("test_field"));
}
}
public void testPayload() throws Exception {
final CompletionMappingBuilder mapping = new CompletionMappingBuilder();
createIndexAndMapping(mapping);
List<IndexRequestBuilder> indexRequestBuilders = new ArrayList<>();
XContentBuilder source = jsonBuilder()
.startObject()
.startObject(FIELD)
.field("input", "suggest")
.field("weight", 1)
.endObject()
.field("title", "title1")
.field("count", 1)
.endObject();
indexRequestBuilders.add(client().prepareIndex(INDEX, TYPE, "1").setSource(source));
source = jsonBuilder()
.startObject()
.startObject(FIELD)
.field("input", "suggestion")
.field("weight", 2)
.endObject()
.field("title", "title2")
.field("count", 2)
.endObject();
indexRequestBuilders.add(client().prepareIndex(INDEX, TYPE, "2").setSource(source));
indexRandom(true, indexRequestBuilders);
CompletionSuggestionBuilder prefix = SuggestBuilders.completionSuggestion(FIELD).prefix("sugg")
.payload(Arrays.asList("title", "count"));
SearchResponse searchResponse = client().prepareSearch(INDEX).suggest(new SuggestBuilder().addSuggestion("foo", prefix))
.execute().actionGet();
assertNoFailures(searchResponse);
CompletionSuggestion completionSuggestion = searchResponse.getSuggest().getSuggestion("foo");
List<CompletionSuggestion.Entry.Option> options = completionSuggestion.getEntries().get(0).getOptions();
assertThat(options.size(), equalTo(2));
assertThat(options.get(0).getText().toString(), equalTo("suggestion"));
assertThat(options.get(0).getScore(), equalTo(2f));
assertThat(options.get(1).getText().toString(), equalTo("suggest"));
assertThat(options.get(1).getScore(), equalTo(1f));
Map<String, List<Object>> firstPayload = options.get(0).getPayload();
assertThat(firstPayload.keySet(), containsInAnyOrder("title", "count"));
assertThat((String) firstPayload.get("title").get(0), equalTo("title2"));
assertThat((long) firstPayload.get("count").get(0), equalTo(2L));
Map<String, List<Object>> secondPayload = options.get(1).getPayload();
assertThat(secondPayload.keySet(), containsInAnyOrder("title", "count"));
assertThat((String) secondPayload.get("title").get(0), equalTo("title1"));
assertThat((long) secondPayload.get("count").get(0), equalTo(1L));
}
public void testSuggestWithPayload() throws Exception {
final CompletionMappingBuilder mapping = new CompletionMappingBuilder();
createIndexAndMapping(mapping);
int numDocs = randomIntBetween(10, 100);
int numPayloadFields = randomIntBetween(2, 5);
List<IndexRequestBuilder> indexRequestBuilders = new ArrayList<>();
for (int i = 1; i <= numDocs; i++) {
XContentBuilder source = jsonBuilder()
.startObject()
.startObject(FIELD)
.field("input", "suggestion" + i)
.field("weight", i)
.endObject();
for (int j = 0; j < numPayloadFields; j++) {
source.field("test_field" + j, j + "value" + i);
}
source.endObject();
indexRequestBuilders.add(client().prepareIndex(INDEX, TYPE, "" + i).setSource(source));
}
indexRandom(true, indexRequestBuilders);
int suggestionSize = randomIntBetween(1, numDocs);
int numRequestedPayloadFields = randomIntBetween(2, numPayloadFields);
List<String> payloadFields = new ArrayList<>(numRequestedPayloadFields);
for (int i = 0; i < numRequestedPayloadFields; i++) {
payloadFields.add("test_field" + i + ".keyword");
}
CompletionSuggestionBuilder prefix = SuggestBuilders.completionSuggestion(FIELD).prefix("sugg")
.size(suggestionSize).payload(payloadFields);
SearchResponse searchResponse = client().prepareSearch(INDEX).suggest(new SuggestBuilder().addSuggestion("foo", prefix))
.execute().actionGet();
assertNoFailures(searchResponse);
CompletionSuggestion completionSuggestion = searchResponse.getSuggest().getSuggestion("foo");
CompletionSuggestion.Entry options = completionSuggestion.getEntries().get(0);
assertThat(options.getOptions().size(), equalTo(suggestionSize));
int id = numDocs;
for (CompletionSuggestion.Entry.Option option : options) {
assertThat(option.getText().toString(), equalTo("suggestion" + id));
assertThat(option.getPayload().size(), equalTo(numRequestedPayloadFields));
for (int i = 0; i < numRequestedPayloadFields; i++) {
List<Object> fieldValue = option.getPayload().get("test_field" + i + ".keyword");
assertNotNull(fieldValue);
assertThat(fieldValue.size(), equalTo(1));
assertThat((String)fieldValue.get(0), equalTo(i + "value" + id));
}
id--;
}
}
public void testSuggestDocument() throws Exception {
final CompletionMappingBuilder mapping = new CompletionMappingBuilder();
createIndexAndMapping(mapping);

View File

@ -19,14 +19,10 @@
package org.elasticsearch.search.suggest.completion;
import com.carrotsearch.randomizedtesting.generators.RandomStrings;
import org.elasticsearch.common.ParsingException;
import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.unit.Fuzziness;
import org.elasticsearch.common.xcontent.ToXContent;
import org.elasticsearch.search.suggest.AbstractSuggestionBuilderTestCase;
import org.elasticsearch.search.suggest.SuggestBuilder;
import org.elasticsearch.search.suggest.completion.context.CategoryQueryContext;
import org.elasticsearch.search.suggest.completion.context.GeoQueryContext;
@ -35,9 +31,7 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import static org.hamcrest.Matchers.containsString;
public class CompletionSuggesterBuilderTests extends AbstractSuggestionBuilderTestCase<CompletionSuggestionBuilder> {
@ -76,9 +70,6 @@ public class CompletionSuggesterBuilderTests extends AbstractSuggestionBuilderTe
testBuilder.regex(randomAsciiOfLength(10), RegexOptionsTests.randomRegexOptions());
break;
}
List<String> payloads = new ArrayList<>();
Collections.addAll(payloads, generateRandomStringArray(5, 10, false, false));
maybeSet(testBuilder::payload, payloads);
Map<String, List<? extends ToXContent>> contextMap = new HashMap<>();
if (randomBoolean()) {
int numContext = randomIntBetween(1, 5);
@ -116,13 +107,8 @@ public class CompletionSuggesterBuilderTests extends AbstractSuggestionBuilderTe
@Override
protected void mutateSpecificParameters(CompletionSuggestionBuilder builder) throws IOException {
switch (randomIntBetween(0, 5)) {
switch (randomIntBetween(0, 4)) {
case 0:
List<String> payloads = new ArrayList<>();
Collections.addAll(payloads, generateRandomStringArray(5, 10, false, false));
builder.payload(payloads);
break;
case 1:
int nCatContext = randomIntBetween(1, 5);
List<CategoryQueryContext> contexts = new ArrayList<>(nCatContext);
for (int i = 0; i < nCatContext; i++) {
@ -130,7 +116,7 @@ public class CompletionSuggesterBuilderTests extends AbstractSuggestionBuilderTe
}
builder.contexts(Collections.singletonMap(randomAsciiOfLength(10), contexts));
break;
case 2:
case 1:
int nGeoContext = randomIntBetween(1, 5);
List<GeoQueryContext> geoContexts = new ArrayList<>(nGeoContext);
for (int i = 0; i < nGeoContext; i++) {
@ -138,39 +124,17 @@ public class CompletionSuggesterBuilderTests extends AbstractSuggestionBuilderTe
}
builder.contexts(Collections.singletonMap(randomAsciiOfLength(10), geoContexts));
break;
case 3:
case 2:
builder.prefix(randomAsciiOfLength(10), FuzzyOptionsTests.randomFuzzyOptions());
break;
case 4:
case 3:
builder.prefix(randomAsciiOfLength(10), randomFrom(Fuzziness.ZERO, Fuzziness.ONE, Fuzziness.TWO));
break;
case 5:
case 4:
builder.regex(randomAsciiOfLength(10), RegexOptionsTests.randomRegexOptions());
break;
default:
throw new IllegalStateException("should not through");
}
}
/**
* Test that a malformed JSON suggestion request fails.
*/
public void testMalformedJsonRequestPayload() throws Exception {
final String field = RandomStrings.randomAsciiOfLength(random(), 10).toLowerCase(Locale.ROOT);
final String payload = "{\n" +
" \"bad-payload\" : { \n" +
" \"prefix\" : \"sug\",\n" +
" \"completion\" : { \n" +
" \"field\" : \"" + field + "\",\n " +
" \"payload\" : [ {\"payload\":\"field\"} ]\n" +
" }\n" +
" }\n" +
"}\n";
try {
final SuggestBuilder suggestBuilder = SuggestBuilder.fromXContent(newParseContext(payload), suggesters);
fail("Should not have been able to create SuggestBuilder from malformed JSON: " + suggestBuilder);
} catch (ParsingException e) {
assertThat(e.getMessage(), containsString("failed to parse field [payload]"));
}
}
}

View File

@ -47,7 +47,7 @@ public class CompletionSuggestionTests extends ESTestCase {
for (int i = 0; i < totalResults; i++) {
Suggest.Suggestion<CompletionSuggestion.Entry> suggestion = randomFrom(shardSuggestions);
suggestion.getEntries().get(0).addOption(new CompletionSuggestion.Entry.Option(i, new Text(""),
maxScore - i, Collections.emptyMap(), Collections.emptyMap()));
maxScore - i, Collections.emptyMap()));
}
CompletionSuggestion reducedSuggestion = CompletionSuggestion.reduceTo(shardSuggestions);
assertNotNull(reducedSuggestion);

View File

@ -195,80 +195,11 @@ returns this response:
// TESTRESPONSE
The configured weight for a suggestion is returned as `_score`.
The `text` field uses the `input` of your indexed suggestion. The document
source is returned in `_source`. <<search-request-source-filtering, source filtering>>
The `text` field uses the `input` of your indexed suggestion.
Suggestions are document oriented, the document source is
returned in `_source`. <<search-request-source-filtering, source filtering>>
parameters are supported for filtering the document source.
Suggestions are document oriented, you can specify fields to be
returned as part of suggestion payload. All field types (`string`,
`numeric`, `date`, etc) are supported.
For example, if you index a "title" field along with the suggestion
as follows:
[source,js]
--------------------------------------------------
PUT music/song/2?refresh
{
"suggest" : "Nirvana",
"title" : "Nevermind"
}
--------------------------------------------------
// CONSOLE
You can get the "title" as part of the suggestion
payload by specifying it as a `payload`:
[source,js]
--------------------------------------------------
POST music/_suggest?pretty
{
"song-suggest" : {
"prefix" : "n",
"completion" : {
"field" : "suggest",
"payload" : [ "title" ] <1>
}
}
}
--------------------------------------------------
// CONSOLE
// TEST[continued]
returns:
[source,js]
--------------------------------------------------
{
"_shards" : {
"total" : 5,
"successful" : 5,
"failed" : 0
},
"song-suggest" : [ {
"text" : "n",
"offset" : 0,
"length" : 1,
"options" : [ {
"text" : "Nirvana",
"_index": "music",
"_type": "song",
"_id": "2",
"_score" : 1.0,
"_source": {
"title": "Nevermind",
"suggest": "Nirvana"
},
"payload" : {
"title" : [ "Nevermind" ]
}
} ]
} ]
}
--------------------------------------------------
// TESTRESPONSE
<1> The fields to be returned as part of each suggestion payload.
The basic completion suggester query supports the following parameters:
`field`:: The name of the field on which to run the query (required).

View File

@ -233,7 +233,7 @@ setup:
- match: { result.0.options.0.text: "baz" }
---
"Suggestions with payload fields should work":
"Suggestions with source should work":
- do:
index:
@ -269,14 +269,17 @@ setup:
text: "b"
completion:
field: suggest_6
payload: [ title, count ]
- length: { result: 1 }
- length: { result.0.options: 2 }
- match: { result.0.options.0.text: "baz" }
- match: { result.0.options.0.payload.title: ["title_baz"] }
- match: { result.0.options.0.payload.count: [3] }
- match: { result.0.options.0._index: "test" }
- match: { result.0.options.0._type: "test" }
- match: { result.0.options.0._source.title: "title_baz" }
- match: { result.0.options.0._source.count: 3 }
- match: { result.0.options.1.text: "bar" }
- match: { result.0.options.1.payload.title: ["title_bar"] }
- match: { result.0.options.1.payload.count: [4] }
- match: { result.0.options.1._index: "test" }
- match: { result.0.options.1._type: "test" }
- match: { result.0.options.1._source.title: "title_bar" }
- match: { result.0.options.1._source.count: 4 }