Context suggester should filter doc values field (#25858)
The context suggester extracts the context field values from the document but it does not filter doc values field coming from Keyword field. This change filters doc values field when building the context values. Fixes #25404
This commit is contained in:
parent
2f8f440e80
commit
3a59b6a16c
|
@ -19,7 +19,11 @@
|
|||
|
||||
package org.elasticsearch.search.suggest.completion.context;
|
||||
|
||||
import org.apache.lucene.document.SortedDocValuesField;
|
||||
import org.apache.lucene.document.SortedSetDocValuesField;
|
||||
import org.apache.lucene.document.StoredField;
|
||||
import org.apache.lucene.index.IndexableField;
|
||||
import org.apache.lucene.search.SortedSetSortField;
|
||||
import org.elasticsearch.ElasticsearchParseException;
|
||||
import org.elasticsearch.Version;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
|
@ -28,6 +32,7 @@ import org.elasticsearch.common.xcontent.XContentParser.Token;
|
|||
import org.elasticsearch.index.mapper.KeywordFieldMapper;
|
||||
import org.elasticsearch.index.mapper.ParseContext;
|
||||
import org.elasticsearch.index.mapper.ParseContext.Document;
|
||||
import org.elasticsearch.index.mapper.StringFieldType;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
|
@ -136,10 +141,16 @@ public class CategoryContextMapping extends ContextMapping<CategoryQueryContext>
|
|||
IndexableField[] fields = document.getFields(fieldName);
|
||||
values = new HashSet<>(fields.length);
|
||||
for (IndexableField field : fields) {
|
||||
if (field.fieldType() instanceof KeywordFieldMapper.KeywordFieldType) {
|
||||
if (field instanceof SortedDocValuesField ||
|
||||
field instanceof SortedSetDocValuesField ||
|
||||
field instanceof StoredField) {
|
||||
// Ignore doc values and stored fields
|
||||
} else if (field.fieldType() instanceof KeywordFieldMapper.KeywordFieldType) {
|
||||
values.add(field.binaryValue().utf8ToString());
|
||||
} else {
|
||||
} else if (field.fieldType() instanceof StringFieldType) {
|
||||
values.add(field.stringValue());
|
||||
} else {
|
||||
throw new IllegalArgumentException("Failed to parse context field [" + fieldName + "], only keyword and text fields are accepted");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,9 +20,14 @@
|
|||
package org.elasticsearch.search.suggest.completion;
|
||||
|
||||
import org.apache.lucene.document.Field;
|
||||
import org.apache.lucene.document.IntPoint;
|
||||
import org.apache.lucene.document.SortedDocValuesField;
|
||||
import org.apache.lucene.document.SortedSetDocValuesField;
|
||||
import org.apache.lucene.document.StoredField;
|
||||
import org.apache.lucene.document.StringField;
|
||||
import org.apache.lucene.index.IndexableField;
|
||||
import org.apache.lucene.search.suggest.document.ContextSuggestField;
|
||||
import org.apache.lucene.util.BytesRef;
|
||||
import org.elasticsearch.ElasticsearchParseException;
|
||||
import org.elasticsearch.common.compress.CompressedXContent;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
|
@ -32,11 +37,15 @@ import org.elasticsearch.common.xcontent.json.JsonXContent;
|
|||
import org.elasticsearch.index.mapper.CompletionFieldMapper.CompletionFieldType;
|
||||
import org.elasticsearch.index.mapper.DocumentMapper;
|
||||
import org.elasticsearch.index.mapper.FieldMapper;
|
||||
import org.elasticsearch.index.mapper.KeywordFieldMapper;
|
||||
import org.elasticsearch.index.mapper.MappedFieldType;
|
||||
import org.elasticsearch.index.mapper.MapperParsingException;
|
||||
import org.elasticsearch.index.mapper.NumberFieldMapper;
|
||||
import org.elasticsearch.index.mapper.ParseContext;
|
||||
import org.elasticsearch.index.mapper.ParsedDocument;
|
||||
import org.elasticsearch.index.mapper.SourceToParse;
|
||||
import org.elasticsearch.index.mapper.StringFieldType;
|
||||
import org.elasticsearch.index.mapper.TextFieldMapper;
|
||||
import org.elasticsearch.search.suggest.completion.context.CategoryContextMapping;
|
||||
import org.elasticsearch.search.suggest.completion.context.ContextBuilder;
|
||||
import org.elasticsearch.search.suggest.completion.context.ContextMapping;
|
||||
|
@ -46,6 +55,7 @@ import java.util.List;
|
|||
import java.util.Set;
|
||||
|
||||
import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
|
||||
public class CategoryContextMappingTests extends ESSingleNodeTestCase {
|
||||
|
@ -699,10 +709,41 @@ public class CategoryContextMappingTests extends ESSingleNodeTestCase {
|
|||
public void testParsingContextFromDocument() throws Exception {
|
||||
CategoryContextMapping mapping = ContextBuilder.category("cat").field("category").build();
|
||||
ParseContext.Document document = new ParseContext.Document();
|
||||
document.add(new StringField("category", "category1", Field.Store.NO));
|
||||
|
||||
KeywordFieldMapper.KeywordFieldType keyword = new KeywordFieldMapper.KeywordFieldType();
|
||||
keyword.setName("category");
|
||||
document.add(new Field(keyword.name(), new BytesRef("category1"), keyword));
|
||||
// Ignore doc values
|
||||
document.add(new SortedSetDocValuesField(keyword.name(), new BytesRef("category1")));
|
||||
Set<CharSequence> context = mapping.parseContext(document);
|
||||
assertThat(context.size(), equalTo(1));
|
||||
assertTrue(context.contains("category1"));
|
||||
|
||||
|
||||
document = new ParseContext.Document();
|
||||
TextFieldMapper.TextFieldType text = new TextFieldMapper.TextFieldType();
|
||||
text.setName("category");
|
||||
document.add(new Field(text.name(), "category1", text));
|
||||
// Ignore stored field
|
||||
document.add(new StoredField(text.name(), "category1", text));
|
||||
context = mapping.parseContext(document);
|
||||
assertThat(context.size(), equalTo(1));
|
||||
assertTrue(context.contains("category1"));
|
||||
|
||||
document = new ParseContext.Document();
|
||||
document.add(new SortedSetDocValuesField("category", new BytesRef("category")));
|
||||
context = mapping.parseContext(document);
|
||||
assertThat(context.size(), equalTo(0));
|
||||
|
||||
document = new ParseContext.Document();
|
||||
document.add(new SortedDocValuesField("category", new BytesRef("category")));
|
||||
context = mapping.parseContext(document);
|
||||
assertThat(context.size(), equalTo(0));
|
||||
|
||||
final ParseContext.Document doc = new ParseContext.Document();
|
||||
doc.add(new IntPoint("category", 36));
|
||||
IllegalArgumentException exc = expectThrows(IllegalArgumentException.class, () -> mapping.parseContext(doc));
|
||||
assertThat(exc.getMessage(), containsString("Failed to parse context field [category]"));
|
||||
}
|
||||
|
||||
static void assertContextSuggestFields(IndexableField[] fields, int expected) {
|
||||
|
|
Loading…
Reference in New Issue