Allow different data types for category in Context suggester (#23491)
The "category" in context suggester could be String, Number or Boolean. However with the changes in version 5 this is failing and only accepting String. This will have problem for existing users of Elasticsearch if they choose to migrate to higher version; as their existing Mapping and query will fail as mentioned in a bug #22358 This PR fixes the above mentioned issue and allows user to migrate seamlessly. Closes #22358
This commit is contained in:
parent
c19044ddf6
commit
ec421974b9
|
@ -528,14 +528,10 @@ public class CompletionFieldMapper extends FieldMapper implements ArrayValueMapp
|
|||
if (currentToken == XContentParser.Token.FIELD_NAME) {
|
||||
fieldName = parser.currentName();
|
||||
contextMapping = contextMappings.get(fieldName);
|
||||
} else if (currentToken == XContentParser.Token.VALUE_STRING
|
||||
|| currentToken == XContentParser.Token.START_ARRAY
|
||||
|| currentToken == XContentParser.Token.START_OBJECT) {
|
||||
} else {
|
||||
assert fieldName != null;
|
||||
assert !contextsMap.containsKey(fieldName);
|
||||
contextsMap.put(fieldName, contextMapping.parseContext(parseContext, parser));
|
||||
} else {
|
||||
throw new IllegalArgumentException("contexts must be an object or an array , but was [" + currentToken + "]");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -107,21 +107,24 @@ public class CategoryContextMapping extends ContextMapping<CategoryQueryContext>
|
|||
* </ul>
|
||||
*/
|
||||
@Override
|
||||
public Set<CharSequence> parseContext(ParseContext parseContext, XContentParser parser) throws IOException, ElasticsearchParseException {
|
||||
public Set<CharSequence> parseContext(ParseContext parseContext, XContentParser parser)
|
||||
throws IOException, ElasticsearchParseException {
|
||||
final Set<CharSequence> contexts = new HashSet<>();
|
||||
Token token = parser.currentToken();
|
||||
if (token == Token.VALUE_STRING) {
|
||||
if (token == Token.VALUE_STRING || token == Token.VALUE_NUMBER || token == Token.VALUE_BOOLEAN) {
|
||||
contexts.add(parser.text());
|
||||
} else if (token == Token.START_ARRAY) {
|
||||
while ((token = parser.nextToken()) != Token.END_ARRAY) {
|
||||
if (token == Token.VALUE_STRING) {
|
||||
if (token == Token.VALUE_STRING || token == Token.VALUE_NUMBER || token == Token.VALUE_BOOLEAN) {
|
||||
contexts.add(parser.text());
|
||||
} else {
|
||||
throw new ElasticsearchParseException("context array must have string values");
|
||||
throw new ElasticsearchParseException(
|
||||
"context array must have string, number or boolean values, but was [" + token + "]");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throw new ElasticsearchParseException("contexts must be a string or a list of strings");
|
||||
throw new ElasticsearchParseException(
|
||||
"contexts must be a string, number or boolean or a list of string, number or boolean, but was [" + token + "]");
|
||||
}
|
||||
return contexts;
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@ package org.elasticsearch.search.suggest.completion.context;
|
|||
|
||||
import org.elasticsearch.ElasticsearchParseException;
|
||||
import org.elasticsearch.common.ParseField;
|
||||
import org.elasticsearch.common.ParsingException;
|
||||
import org.elasticsearch.common.xcontent.ObjectParser;
|
||||
import org.elasticsearch.common.xcontent.ToXContent;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
|
@ -98,7 +99,8 @@ public final class CategoryQueryContext implements ToXContent {
|
|||
|
||||
private static ObjectParser<Builder, Void> CATEGORY_PARSER = new ObjectParser<>(NAME, null);
|
||||
static {
|
||||
CATEGORY_PARSER.declareString(Builder::setCategory, new ParseField(CONTEXT_VALUE));
|
||||
CATEGORY_PARSER.declareField(Builder::setCategory, XContentParser::text, new ParseField(CONTEXT_VALUE),
|
||||
ObjectParser.ValueType.VALUE);
|
||||
CATEGORY_PARSER.declareInt(Builder::setBoost, new ParseField(CONTEXT_BOOST));
|
||||
CATEGORY_PARSER.declareBoolean(Builder::setPrefix, new ParseField(CONTEXT_PREFIX));
|
||||
}
|
||||
|
@ -108,11 +110,16 @@ public final class CategoryQueryContext implements ToXContent {
|
|||
XContentParser.Token token = parser.currentToken();
|
||||
Builder builder = builder();
|
||||
if (token == XContentParser.Token.START_OBJECT) {
|
||||
CATEGORY_PARSER.parse(parser, builder, null);
|
||||
} else if (token == XContentParser.Token.VALUE_STRING) {
|
||||
try {
|
||||
CATEGORY_PARSER.parse(parser, builder, null);
|
||||
} catch(ParsingException e) {
|
||||
throw new ElasticsearchParseException("category context must be a string, number or boolean");
|
||||
}
|
||||
} else if (token == XContentParser.Token.VALUE_STRING || token == XContentParser.Token.VALUE_BOOLEAN
|
||||
|| token == XContentParser.Token.VALUE_NUMBER) {
|
||||
builder.setCategory(parser.text());
|
||||
} else {
|
||||
throw new ElasticsearchParseException("category context must be an object or string");
|
||||
throw new ElasticsearchParseException("category context must be an object, string, number or boolean");
|
||||
}
|
||||
return builder.build();
|
||||
}
|
||||
|
|
|
@ -109,13 +109,14 @@ public abstract class ContextMapping<T extends ToXContent> implements ToXContent
|
|||
List<T> queryContexts = new ArrayList<>();
|
||||
XContentParser parser = context.parser();
|
||||
Token token = parser.nextToken();
|
||||
if (token == Token.START_OBJECT || token == Token.VALUE_STRING) {
|
||||
queryContexts.add(fromXContent(context));
|
||||
} else if (token == Token.START_ARRAY) {
|
||||
if (token == Token.START_ARRAY) {
|
||||
while (parser.nextToken() != Token.END_ARRAY) {
|
||||
queryContexts.add(fromXContent(context));
|
||||
}
|
||||
} else {
|
||||
queryContexts.add(fromXContent(context));
|
||||
}
|
||||
|
||||
return toInternalQueryContexts(queryContexts);
|
||||
}
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@ import org.apache.lucene.document.Field;
|
|||
import org.apache.lucene.document.StringField;
|
||||
import org.apache.lucene.index.IndexableField;
|
||||
import org.apache.lucene.search.suggest.document.ContextSuggestField;
|
||||
import org.elasticsearch.ElasticsearchParseException;
|
||||
import org.elasticsearch.common.compress.CompressedXContent;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
|
@ -31,6 +32,7 @@ import org.elasticsearch.common.xcontent.json.JsonXContent;
|
|||
import org.elasticsearch.index.mapper.DocumentMapper;
|
||||
import org.elasticsearch.index.mapper.FieldMapper;
|
||||
import org.elasticsearch.index.mapper.MappedFieldType;
|
||||
import org.elasticsearch.index.mapper.MapperParsingException;
|
||||
import org.elasticsearch.index.mapper.ParseContext;
|
||||
import org.elasticsearch.index.mapper.ParsedDocument;
|
||||
import org.elasticsearch.index.mapper.SourceToParse;
|
||||
|
@ -120,6 +122,103 @@ public class CategoryContextMappingTests extends ESSingleNodeTestCase {
|
|||
IndexableField[] fields = parsedDocument.rootDoc().getFields(completionFieldType.name());
|
||||
assertContextSuggestFields(fields, 3);
|
||||
}
|
||||
|
||||
public void testIndexingWithSimpleNumberContexts() throws Exception {
|
||||
String mapping = jsonBuilder().startObject().startObject("type1")
|
||||
.startObject("properties").startObject("completion")
|
||||
.field("type", "completion")
|
||||
.startArray("contexts")
|
||||
.startObject()
|
||||
.field("name", "ctx")
|
||||
.field("type", "category")
|
||||
.endObject()
|
||||
.endArray()
|
||||
.endObject().endObject()
|
||||
.endObject().endObject().string();
|
||||
|
||||
DocumentMapper defaultMapper = createIndex("test").mapperService().documentMapperParser().parse("type1", new CompressedXContent(mapping));
|
||||
FieldMapper fieldMapper = defaultMapper.mappers().getMapper("completion");
|
||||
MappedFieldType completionFieldType = fieldMapper.fieldType();
|
||||
ParsedDocument parsedDocument = defaultMapper.parse("test", "type1", "1", jsonBuilder()
|
||||
.startObject()
|
||||
.startArray("completion")
|
||||
.startObject()
|
||||
.array("input", "suggestion5", "suggestion6", "suggestion7")
|
||||
.startObject("contexts")
|
||||
.field("ctx", 100)
|
||||
.endObject()
|
||||
.field("weight", 5)
|
||||
.endObject()
|
||||
.endArray()
|
||||
.endObject()
|
||||
.bytes());
|
||||
IndexableField[] fields = parsedDocument.rootDoc().getFields(completionFieldType.name());
|
||||
assertContextSuggestFields(fields, 3);
|
||||
}
|
||||
|
||||
public void testIndexingWithSimpleBooleanContexts() throws Exception {
|
||||
String mapping = jsonBuilder().startObject().startObject("type1")
|
||||
.startObject("properties").startObject("completion")
|
||||
.field("type", "completion")
|
||||
.startArray("contexts")
|
||||
.startObject()
|
||||
.field("name", "ctx")
|
||||
.field("type", "category")
|
||||
.endObject()
|
||||
.endArray()
|
||||
.endObject().endObject()
|
||||
.endObject().endObject().string();
|
||||
|
||||
DocumentMapper defaultMapper = createIndex("test").mapperService().documentMapperParser().parse("type1", new CompressedXContent(mapping));
|
||||
FieldMapper fieldMapper = defaultMapper.mappers().getMapper("completion");
|
||||
MappedFieldType completionFieldType = fieldMapper.fieldType();
|
||||
ParsedDocument parsedDocument = defaultMapper.parse("test", "type1", "1", jsonBuilder()
|
||||
.startObject()
|
||||
.startArray("completion")
|
||||
.startObject()
|
||||
.array("input", "suggestion5", "suggestion6", "suggestion7")
|
||||
.startObject("contexts")
|
||||
.field("ctx", true)
|
||||
.endObject()
|
||||
.field("weight", 5)
|
||||
.endObject()
|
||||
.endArray()
|
||||
.endObject()
|
||||
.bytes());
|
||||
IndexableField[] fields = parsedDocument.rootDoc().getFields(completionFieldType.name());
|
||||
assertContextSuggestFields(fields, 3);
|
||||
}
|
||||
|
||||
public void testIndexingWithSimpleNULLContexts() throws Exception {
|
||||
String mapping = jsonBuilder().startObject().startObject("type1")
|
||||
.startObject("properties").startObject("completion")
|
||||
.field("type", "completion")
|
||||
.startArray("contexts")
|
||||
.startObject()
|
||||
.field("name", "ctx")
|
||||
.field("type", "category")
|
||||
.endObject()
|
||||
.endArray()
|
||||
.endObject().endObject()
|
||||
.endObject().endObject().string();
|
||||
|
||||
DocumentMapper defaultMapper = createIndex("test").mapperService().documentMapperParser().parse("type1", new CompressedXContent(mapping));
|
||||
XContentBuilder builder = jsonBuilder()
|
||||
.startObject()
|
||||
.startArray("completion")
|
||||
.startObject()
|
||||
.array("input", "suggestion5", "suggestion6", "suggestion7")
|
||||
.startObject("contexts")
|
||||
.nullField("ctx")
|
||||
.endObject()
|
||||
.field("weight", 5)
|
||||
.endObject()
|
||||
.endArray()
|
||||
.endObject();
|
||||
|
||||
Exception e = expectThrows(MapperParsingException.class, () -> defaultMapper.parse("test", "type1", "1", builder.bytes()));
|
||||
assertEquals("contexts must be a string, number or boolean or a list of string, number or boolean, but was [VALUE_NULL]", e.getCause().getMessage());
|
||||
}
|
||||
|
||||
public void testIndexingWithContextList() throws Exception {
|
||||
String mapping = jsonBuilder().startObject().startObject("type1")
|
||||
|
@ -152,6 +251,66 @@ public class CategoryContextMappingTests extends ESSingleNodeTestCase {
|
|||
IndexableField[] fields = parsedDocument.rootDoc().getFields(completionFieldType.name());
|
||||
assertContextSuggestFields(fields, 3);
|
||||
}
|
||||
|
||||
public void testIndexingWithMixedTypeContextList() throws Exception {
|
||||
String mapping = jsonBuilder().startObject().startObject("type1")
|
||||
.startObject("properties").startObject("completion")
|
||||
.field("type", "completion")
|
||||
.startArray("contexts")
|
||||
.startObject()
|
||||
.field("name", "ctx")
|
||||
.field("type", "category")
|
||||
.endObject()
|
||||
.endArray()
|
||||
.endObject().endObject()
|
||||
.endObject().endObject().string();
|
||||
|
||||
DocumentMapper defaultMapper = createIndex("test").mapperService().documentMapperParser().parse("type1", new CompressedXContent(mapping));
|
||||
FieldMapper fieldMapper = defaultMapper.mappers().getMapper("completion");
|
||||
MappedFieldType completionFieldType = fieldMapper.fieldType();
|
||||
ParsedDocument parsedDocument = defaultMapper.parse("test", "type1", "1", jsonBuilder()
|
||||
.startObject()
|
||||
.startObject("completion")
|
||||
.array("input", "suggestion5", "suggestion6", "suggestion7")
|
||||
.startObject("contexts")
|
||||
.array("ctx", "ctx1", true, 100)
|
||||
.endObject()
|
||||
.field("weight", 5)
|
||||
.endObject()
|
||||
.endObject()
|
||||
.bytes());
|
||||
IndexableField[] fields = parsedDocument.rootDoc().getFields(completionFieldType.name());
|
||||
assertContextSuggestFields(fields, 3);
|
||||
}
|
||||
|
||||
public void testIndexingWithMixedTypeContextListHavingNULL() throws Exception {
|
||||
String mapping = jsonBuilder().startObject().startObject("type1")
|
||||
.startObject("properties").startObject("completion")
|
||||
.field("type", "completion")
|
||||
.startArray("contexts")
|
||||
.startObject()
|
||||
.field("name", "ctx")
|
||||
.field("type", "category")
|
||||
.endObject()
|
||||
.endArray()
|
||||
.endObject().endObject()
|
||||
.endObject().endObject().string();
|
||||
|
||||
DocumentMapper defaultMapper = createIndex("test").mapperService().documentMapperParser().parse("type1", new CompressedXContent(mapping));
|
||||
XContentBuilder builder = jsonBuilder()
|
||||
.startObject()
|
||||
.startObject("completion")
|
||||
.array("input", "suggestion5", "suggestion6", "suggestion7")
|
||||
.startObject("contexts")
|
||||
.array("ctx", "ctx1", true, 100, null)
|
||||
.endObject()
|
||||
.field("weight", 5)
|
||||
.endObject()
|
||||
.endObject();
|
||||
|
||||
Exception e = expectThrows(MapperParsingException.class, () -> defaultMapper.parse("test", "type1", "1", builder.bytes()));
|
||||
assertEquals("context array must have string, number or boolean values, but was [VALUE_NULL]", e.getCause().getMessage());
|
||||
}
|
||||
|
||||
public void testIndexingWithMultipleContexts() throws Exception {
|
||||
String mapping = jsonBuilder().startObject().startObject("type1")
|
||||
|
@ -202,6 +361,37 @@ public class CategoryContextMappingTests extends ESSingleNodeTestCase {
|
|||
assertThat(internalQueryContexts.get(0).boost, equalTo(1));
|
||||
assertThat(internalQueryContexts.get(0).isPrefix, equalTo(false));
|
||||
}
|
||||
|
||||
public void testBooleanQueryContextParsingBasic() throws Exception {
|
||||
XContentBuilder builder = jsonBuilder().value(true);
|
||||
XContentParser parser = createParser(JsonXContent.jsonXContent, builder.bytes());
|
||||
CategoryContextMapping mapping = ContextBuilder.category("cat").build();
|
||||
List<ContextMapping.InternalQueryContext> internalQueryContexts = mapping.parseQueryContext(createParseContext(parser));
|
||||
assertThat(internalQueryContexts.size(), equalTo(1));
|
||||
assertThat(internalQueryContexts.get(0).context, equalTo("true"));
|
||||
assertThat(internalQueryContexts.get(0).boost, equalTo(1));
|
||||
assertThat(internalQueryContexts.get(0).isPrefix, equalTo(false));
|
||||
}
|
||||
|
||||
public void testNumberQueryContextParsingBasic() throws Exception {
|
||||
XContentBuilder builder = jsonBuilder().value(10);
|
||||
XContentParser parser = createParser(JsonXContent.jsonXContent, builder.bytes());
|
||||
CategoryContextMapping mapping = ContextBuilder.category("cat").build();
|
||||
List<ContextMapping.InternalQueryContext> internalQueryContexts = mapping.parseQueryContext(createParseContext(parser));
|
||||
assertThat(internalQueryContexts.size(), equalTo(1));
|
||||
assertThat(internalQueryContexts.get(0).context, equalTo("10"));
|
||||
assertThat(internalQueryContexts.get(0).boost, equalTo(1));
|
||||
assertThat(internalQueryContexts.get(0).isPrefix, equalTo(false));
|
||||
}
|
||||
|
||||
public void testNULLQueryContextParsingBasic() throws Exception {
|
||||
XContentBuilder builder = jsonBuilder().nullValue();
|
||||
XContentParser parser = createParser(JsonXContent.jsonXContent, builder.bytes());
|
||||
CategoryContextMapping mapping = ContextBuilder.category("cat").build();
|
||||
|
||||
Exception e = expectThrows(ElasticsearchParseException.class, () -> mapping.parseQueryContext(createParseContext(parser)));
|
||||
assertEquals("category context must be an object, string, number or boolean", e.getMessage());
|
||||
}
|
||||
|
||||
public void testQueryContextParsingArray() throws Exception {
|
||||
XContentBuilder builder = jsonBuilder().startArray()
|
||||
|
@ -219,6 +409,46 @@ public class CategoryContextMappingTests extends ESSingleNodeTestCase {
|
|||
assertThat(internalQueryContexts.get(1).boost, equalTo(1));
|
||||
assertThat(internalQueryContexts.get(1).isPrefix, equalTo(false));
|
||||
}
|
||||
|
||||
public void testQueryContextParsingMixedTypeValuesArray() throws Exception {
|
||||
XContentBuilder builder = jsonBuilder().startArray()
|
||||
.value("context1")
|
||||
.value("context2")
|
||||
.value(true)
|
||||
.value(10)
|
||||
.endArray();
|
||||
XContentParser parser = createParser(JsonXContent.jsonXContent, builder.bytes());
|
||||
CategoryContextMapping mapping = ContextBuilder.category("cat").build();
|
||||
List<ContextMapping.InternalQueryContext> internalQueryContexts = mapping.parseQueryContext(createParseContext(parser));
|
||||
assertThat(internalQueryContexts.size(), equalTo(4));
|
||||
assertThat(internalQueryContexts.get(0).context, equalTo("context1"));
|
||||
assertThat(internalQueryContexts.get(0).boost, equalTo(1));
|
||||
assertThat(internalQueryContexts.get(0).isPrefix, equalTo(false));
|
||||
assertThat(internalQueryContexts.get(1).context, equalTo("context2"));
|
||||
assertThat(internalQueryContexts.get(1).boost, equalTo(1));
|
||||
assertThat(internalQueryContexts.get(1).isPrefix, equalTo(false));
|
||||
assertThat(internalQueryContexts.get(2).context, equalTo("true"));
|
||||
assertThat(internalQueryContexts.get(2).boost, equalTo(1));
|
||||
assertThat(internalQueryContexts.get(2).isPrefix, equalTo(false));
|
||||
assertThat(internalQueryContexts.get(3).context, equalTo("10"));
|
||||
assertThat(internalQueryContexts.get(3).boost, equalTo(1));
|
||||
assertThat(internalQueryContexts.get(3).isPrefix, equalTo(false));
|
||||
}
|
||||
|
||||
public void testQueryContextParsingMixedTypeValuesArrayHavingNULL() throws Exception {
|
||||
XContentBuilder builder = jsonBuilder().startArray()
|
||||
.value("context1")
|
||||
.value("context2")
|
||||
.value(true)
|
||||
.value(10)
|
||||
.nullValue()
|
||||
.endArray();
|
||||
XContentParser parser = createParser(JsonXContent.jsonXContent, builder.bytes());
|
||||
CategoryContextMapping mapping = ContextBuilder.category("cat").build();
|
||||
|
||||
Exception e = expectThrows(ElasticsearchParseException.class, () -> mapping.parseQueryContext(createParseContext(parser)));
|
||||
assertEquals("category context must be an object, string, number or boolean", e.getMessage());
|
||||
}
|
||||
|
||||
public void testQueryContextParsingObject() throws Exception {
|
||||
XContentBuilder builder = jsonBuilder().startObject()
|
||||
|
@ -235,7 +465,49 @@ public class CategoryContextMappingTests extends ESSingleNodeTestCase {
|
|||
assertThat(internalQueryContexts.get(0).isPrefix, equalTo(true));
|
||||
}
|
||||
|
||||
public void testQueryContextParsingObjectHavingBoolean() throws Exception {
|
||||
XContentBuilder builder = jsonBuilder().startObject()
|
||||
.field("context", false)
|
||||
.field("boost", 10)
|
||||
.field("prefix", true)
|
||||
.endObject();
|
||||
XContentParser parser = createParser(JsonXContent.jsonXContent, builder.bytes());
|
||||
CategoryContextMapping mapping = ContextBuilder.category("cat").build();
|
||||
List<ContextMapping.InternalQueryContext> internalQueryContexts = mapping.parseQueryContext(createParseContext(parser));
|
||||
assertThat(internalQueryContexts.size(), equalTo(1));
|
||||
assertThat(internalQueryContexts.get(0).context, equalTo("false"));
|
||||
assertThat(internalQueryContexts.get(0).boost, equalTo(10));
|
||||
assertThat(internalQueryContexts.get(0).isPrefix, equalTo(true));
|
||||
}
|
||||
|
||||
public void testQueryContextParsingObjectHavingNumber() throws Exception {
|
||||
XContentBuilder builder = jsonBuilder().startObject()
|
||||
.field("context", 333)
|
||||
.field("boost", 10)
|
||||
.field("prefix", true)
|
||||
.endObject();
|
||||
XContentParser parser = createParser(JsonXContent.jsonXContent, builder.bytes());
|
||||
CategoryContextMapping mapping = ContextBuilder.category("cat").build();
|
||||
List<ContextMapping.InternalQueryContext> internalQueryContexts = mapping.parseQueryContext(createParseContext(parser));
|
||||
assertThat(internalQueryContexts.size(), equalTo(1));
|
||||
assertThat(internalQueryContexts.get(0).context, equalTo("333"));
|
||||
assertThat(internalQueryContexts.get(0).boost, equalTo(10));
|
||||
assertThat(internalQueryContexts.get(0).isPrefix, equalTo(true));
|
||||
}
|
||||
|
||||
public void testQueryContextParsingObjectHavingNULL() throws Exception {
|
||||
XContentBuilder builder = jsonBuilder().startObject()
|
||||
.nullField("context")
|
||||
.field("boost", 10)
|
||||
.field("prefix", true)
|
||||
.endObject();
|
||||
XContentParser parser = createParser(JsonXContent.jsonXContent, builder.bytes());
|
||||
CategoryContextMapping mapping = ContextBuilder.category("cat").build();
|
||||
|
||||
Exception e = expectThrows(ElasticsearchParseException.class, () -> mapping.parseQueryContext(createParseContext(parser)));
|
||||
assertEquals("category context must be a string, number or boolean", e.getMessage());
|
||||
}
|
||||
|
||||
public void testQueryContextParsingObjectArray() throws Exception {
|
||||
XContentBuilder builder = jsonBuilder().startArray()
|
||||
.startObject()
|
||||
|
@ -260,6 +532,82 @@ public class CategoryContextMappingTests extends ESSingleNodeTestCase {
|
|||
assertThat(internalQueryContexts.get(1).boost, equalTo(3));
|
||||
assertThat(internalQueryContexts.get(1).isPrefix, equalTo(false));
|
||||
}
|
||||
|
||||
public void testQueryContextParsingMixedTypeObjectArray() throws Exception {
|
||||
XContentBuilder builder = jsonBuilder().startArray()
|
||||
.startObject()
|
||||
.field("context", "context1")
|
||||
.field("boost", 2)
|
||||
.field("prefix", true)
|
||||
.endObject()
|
||||
.startObject()
|
||||
.field("context", "context2")
|
||||
.field("boost", 3)
|
||||
.field("prefix", false)
|
||||
.endObject()
|
||||
.startObject()
|
||||
.field("context", true)
|
||||
.field("boost", 3)
|
||||
.field("prefix", false)
|
||||
.endObject()
|
||||
.startObject()
|
||||
.field("context", 333)
|
||||
.field("boost", 3)
|
||||
.field("prefix", false)
|
||||
.endObject()
|
||||
.endArray();
|
||||
XContentParser parser = createParser(JsonXContent.jsonXContent, builder.bytes());
|
||||
CategoryContextMapping mapping = ContextBuilder.category("cat").build();
|
||||
List<ContextMapping.InternalQueryContext> internalQueryContexts = mapping.parseQueryContext(createParseContext(parser));
|
||||
assertThat(internalQueryContexts.size(), equalTo(4));
|
||||
assertThat(internalQueryContexts.get(0).context, equalTo("context1"));
|
||||
assertThat(internalQueryContexts.get(0).boost, equalTo(2));
|
||||
assertThat(internalQueryContexts.get(0).isPrefix, equalTo(true));
|
||||
assertThat(internalQueryContexts.get(1).context, equalTo("context2"));
|
||||
assertThat(internalQueryContexts.get(1).boost, equalTo(3));
|
||||
assertThat(internalQueryContexts.get(1).isPrefix, equalTo(false));
|
||||
assertThat(internalQueryContexts.get(2).context, equalTo("true"));
|
||||
assertThat(internalQueryContexts.get(2).boost, equalTo(3));
|
||||
assertThat(internalQueryContexts.get(2).isPrefix, equalTo(false));
|
||||
assertThat(internalQueryContexts.get(3).context, equalTo("333"));
|
||||
assertThat(internalQueryContexts.get(3).boost, equalTo(3));
|
||||
assertThat(internalQueryContexts.get(3).isPrefix, equalTo(false));
|
||||
}
|
||||
|
||||
public void testQueryContextParsingMixedTypeObjectArrayHavingNULL() throws Exception {
|
||||
XContentBuilder builder = jsonBuilder().startArray()
|
||||
.startObject()
|
||||
.field("context", "context1")
|
||||
.field("boost", 2)
|
||||
.field("prefix", true)
|
||||
.endObject()
|
||||
.startObject()
|
||||
.field("context", "context2")
|
||||
.field("boost", 3)
|
||||
.field("prefix", false)
|
||||
.endObject()
|
||||
.startObject()
|
||||
.field("context", true)
|
||||
.field("boost", 3)
|
||||
.field("prefix", false)
|
||||
.endObject()
|
||||
.startObject()
|
||||
.field("context", 333)
|
||||
.field("boost", 3)
|
||||
.field("prefix", false)
|
||||
.endObject()
|
||||
.startObject()
|
||||
.nullField("context")
|
||||
.field("boost", 3)
|
||||
.field("prefix", false)
|
||||
.endObject()
|
||||
.endArray();
|
||||
XContentParser parser = createParser(JsonXContent.jsonXContent, builder.bytes());
|
||||
CategoryContextMapping mapping = ContextBuilder.category("cat").build();
|
||||
|
||||
Exception e = expectThrows(ElasticsearchParseException.class, () -> mapping.parseQueryContext(createParseContext(parser)));
|
||||
assertEquals("category context must be a string, number or boolean", e.getMessage());
|
||||
}
|
||||
|
||||
private static QueryParseContext createParseContext(XContentParser parser) {
|
||||
return new QueryParseContext(parser);
|
||||
|
@ -273,17 +621,52 @@ public class CategoryContextMappingTests extends ESSingleNodeTestCase {
|
|||
.field("prefix", true)
|
||||
.endObject()
|
||||
.value("context2")
|
||||
.value(false)
|
||||
.startObject()
|
||||
.field("context", 333)
|
||||
.field("boost", 2)
|
||||
.field("prefix", true)
|
||||
.endObject()
|
||||
.endArray();
|
||||
XContentParser parser = createParser(JsonXContent.jsonXContent, builder.bytes());
|
||||
CategoryContextMapping mapping = ContextBuilder.category("cat").build();
|
||||
List<ContextMapping.InternalQueryContext> internalQueryContexts = mapping.parseQueryContext(createParseContext(parser));
|
||||
assertThat(internalQueryContexts.size(), equalTo(2));
|
||||
assertThat(internalQueryContexts.size(), equalTo(4));
|
||||
assertThat(internalQueryContexts.get(0).context, equalTo("context1"));
|
||||
assertThat(internalQueryContexts.get(0).boost, equalTo(2));
|
||||
assertThat(internalQueryContexts.get(0).isPrefix, equalTo(true));
|
||||
assertThat(internalQueryContexts.get(1).context, equalTo("context2"));
|
||||
assertThat(internalQueryContexts.get(1).boost, equalTo(1));
|
||||
assertThat(internalQueryContexts.get(1).isPrefix, equalTo(false));
|
||||
assertThat(internalQueryContexts.get(2).context, equalTo("false"));
|
||||
assertThat(internalQueryContexts.get(2).boost, equalTo(1));
|
||||
assertThat(internalQueryContexts.get(2).isPrefix, equalTo(false));
|
||||
assertThat(internalQueryContexts.get(3).context, equalTo("333"));
|
||||
assertThat(internalQueryContexts.get(3).boost, equalTo(2));
|
||||
assertThat(internalQueryContexts.get(3).isPrefix, equalTo(true));
|
||||
}
|
||||
|
||||
public void testQueryContextParsingMixedHavingNULL() throws Exception {
|
||||
XContentBuilder builder = jsonBuilder().startArray()
|
||||
.startObject()
|
||||
.field("context", "context1")
|
||||
.field("boost", 2)
|
||||
.field("prefix", true)
|
||||
.endObject()
|
||||
.value("context2")
|
||||
.value(false)
|
||||
.startObject()
|
||||
.field("context", 333)
|
||||
.field("boost", 2)
|
||||
.field("prefix", true)
|
||||
.endObject()
|
||||
.nullValue()
|
||||
.endArray();
|
||||
XContentParser parser = createParser(JsonXContent.jsonXContent, builder.bytes());
|
||||
CategoryContextMapping mapping = ContextBuilder.category("cat").build();
|
||||
|
||||
Exception e = expectThrows(ElasticsearchParseException.class, () -> mapping.parseQueryContext(createParseContext(parser)));
|
||||
assertEquals("category context must be an object, string, number or boolean", e.getMessage());
|
||||
}
|
||||
|
||||
public void testParsingContextFromDocument() throws Exception {
|
||||
|
|
Loading…
Reference in New Issue