Fix cross type mapping updates for `boolean` fields. #17882

Boolean fields were not handled in `DocumentParser.createBuilderFromFieldType`.
This also improves the logic a bit by falling back to the default mapping of
the given type insteah of hard-coding every case and throws a better exception
than a NPE if no dynamic mappings could be created.

Closes #17879
This commit is contained in:
Adrien Grand 2016-04-20 09:39:53 +02:00
parent f245fc1ccd
commit ab168996b6
2 changed files with 27 additions and 39 deletions

View File

@ -22,6 +22,7 @@ package org.elasticsearch.index.mapper;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
@ -593,9 +594,6 @@ final class DocumentParser {
Mapper.Builder builder = null; Mapper.Builder builder = null;
if (fieldType instanceof StringFieldType) { if (fieldType instanceof StringFieldType) {
builder = context.root().findTemplateBuilder(context, currentFieldName, "string", "string"); builder = context.root().findTemplateBuilder(context, currentFieldName, "string", "string");
if (builder == null) {
builder = new StringFieldMapper.Builder(currentFieldName);
}
} else if (fieldType instanceof TextFieldType) { } else if (fieldType instanceof TextFieldType) {
builder = context.root().findTemplateBuilder(context, currentFieldName, "text", "string"); builder = context.root().findTemplateBuilder(context, currentFieldName, "text", "string");
if (builder == null) { if (builder == null) {
@ -604,45 +602,39 @@ final class DocumentParser {
} }
} else if (fieldType instanceof KeywordFieldType) { } else if (fieldType instanceof KeywordFieldType) {
builder = context.root().findTemplateBuilder(context, currentFieldName, "keyword", "string"); builder = context.root().findTemplateBuilder(context, currentFieldName, "keyword", "string");
if (builder == null) {
builder = new KeywordFieldMapper.Builder(currentFieldName);
}
} else { } else {
switch (fieldType.typeName()) { switch (fieldType.typeName()) {
case "date": case DateFieldMapper.CONTENT_TYPE:
builder = context.root().findTemplateBuilder(context, currentFieldName, "date"); builder = context.root().findTemplateBuilder(context, currentFieldName, "date");
if (builder == null) {
builder = newDateBuilder(currentFieldName, null, Version.indexCreated(context.indexSettings()));
}
break; break;
case "long": case "long":
builder = context.root().findTemplateBuilder(context, currentFieldName, "long"); builder = context.root().findTemplateBuilder(context, currentFieldName, "long");
if (builder == null) {
builder = newLongBuilder(currentFieldName, Version.indexCreated(context.indexSettings()));
}
break; break;
case "double": case "double":
builder = context.root().findTemplateBuilder(context, currentFieldName, "double"); builder = context.root().findTemplateBuilder(context, currentFieldName, "double");
if (builder == null) {
builder = newDoubleBuilder(currentFieldName, Version.indexCreated(context.indexSettings()));
}
break; break;
case "integer": case "integer":
builder = context.root().findTemplateBuilder(context, currentFieldName, "integer"); builder = context.root().findTemplateBuilder(context, currentFieldName, "integer");
if (builder == null) {
builder = newIntBuilder(currentFieldName, Version.indexCreated(context.indexSettings()));
}
break; break;
case "float": case "float":
builder = context.root().findTemplateBuilder(context, currentFieldName, "float"); builder = context.root().findTemplateBuilder(context, currentFieldName, "float");
if (builder == null) { break;
builder = newFloatBuilder(currentFieldName, Version.indexCreated(context.indexSettings())); case BooleanFieldMapper.CONTENT_TYPE:
} builder = context.root().findTemplateBuilder(context, currentFieldName, "boolean");
break; break;
default: default:
break; break;
} }
} }
if (builder == null) {
Mapper.TypeParser.ParserContext parserContext = context.docMapperParser().parserContext(currentFieldName);
Mapper.TypeParser typeParser = parserContext.typeParser(fieldType.typeName());
if (typeParser == null) {
throw new MapperParsingException("Cannot generate dynamic mappings of type [" + fieldType.typeName()
+ "] for [" + currentFieldName + "]");
}
builder = typeParser.parse(currentFieldName, new HashMap<>(), parserContext);
}
return builder; return builder;
} }
@ -654,22 +646,6 @@ final class DocumentParser {
} }
} }
private static Mapper.Builder<?, ?> newIntBuilder(String name, Version indexCreated) {
if (indexCreated.onOrAfter(Version.V_5_0_0)) {
return new NumberFieldMapper.Builder(name, NumberFieldMapper.NumberType.INTEGER);
} else {
return new LegacyIntegerFieldMapper.Builder(name);
}
}
private static Mapper.Builder<?, ?> newDoubleBuilder(String name, Version indexCreated) {
if (indexCreated.onOrAfter(Version.V_5_0_0)) {
return new NumberFieldMapper.Builder(name, NumberFieldMapper.NumberType.DOUBLE);
} else {
return new LegacyDoubleFieldMapper.Builder(name);
}
}
private static Mapper.Builder<?, ?> newFloatBuilder(String name, Version indexCreated) { private static Mapper.Builder<?, ?> newFloatBuilder(String name, Version indexCreated) {
if (indexCreated.onOrAfter(Version.V_5_0_0)) { if (indexCreated.onOrAfter(Version.V_5_0_0)) {
return new NumberFieldMapper.Builder(name, NumberFieldMapper.NumberType.FLOAT); return new NumberFieldMapper.Builder(name, NumberFieldMapper.NumberType.FLOAT);

View File

@ -31,6 +31,8 @@ import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.common.xcontent.XContentHelper; import org.elasticsearch.common.xcontent.XContentHelper;
import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.index.IndexService; import org.elasticsearch.index.IndexService;
import org.elasticsearch.index.mapper.core.BooleanFieldMapper;
import org.elasticsearch.index.mapper.core.BooleanFieldMapper.BooleanFieldType;
import org.elasticsearch.index.mapper.core.DateFieldMapper; import org.elasticsearch.index.mapper.core.DateFieldMapper;
import org.elasticsearch.index.mapper.core.DateFieldMapper.DateFieldType; import org.elasticsearch.index.mapper.core.DateFieldMapper.DateFieldType;
import org.elasticsearch.index.mapper.core.NumberFieldMapper; import org.elasticsearch.index.mapper.core.NumberFieldMapper;
@ -429,7 +431,8 @@ public class DynamicMappingTests extends ESSingleNodeTestCase {
"my_field3", "type=long,doc_values=false", "my_field3", "type=long,doc_values=false",
"my_field4", "type=float,index=false", "my_field4", "type=float,index=false",
"my_field5", "type=double,store=true", "my_field5", "type=double,store=true",
"my_field6", "type=date,doc_values=false"); "my_field6", "type=date,doc_values=false",
"my_field7", "type=boolean,doc_values=false");
// Even if the dynamic type of our new field is long, we already have a mapping for the same field // Even if the dynamic type of our new field is long, we already have a mapping for the same field
// of type string so it should be mapped as a string // of type string so it should be mapped as a string
@ -442,6 +445,7 @@ public class DynamicMappingTests extends ESSingleNodeTestCase {
.field("my_field4", 45) .field("my_field4", 45)
.field("my_field5", 46) .field("my_field5", 46)
.field("my_field6", 47) .field("my_field6", 47)
.field("my_field7", true)
.endObject()); .endObject());
Mapper myField1Mapper = null; Mapper myField1Mapper = null;
Mapper myField2Mapper = null; Mapper myField2Mapper = null;
@ -449,6 +453,7 @@ public class DynamicMappingTests extends ESSingleNodeTestCase {
Mapper myField4Mapper = null; Mapper myField4Mapper = null;
Mapper myField5Mapper = null; Mapper myField5Mapper = null;
Mapper myField6Mapper = null; Mapper myField6Mapper = null;
Mapper myField7Mapper = null;
for (Mapper m : update) { for (Mapper m : update) {
switch (m.name()) { switch (m.name()) {
case "my_field1": case "my_field1":
@ -469,6 +474,9 @@ public class DynamicMappingTests extends ESSingleNodeTestCase {
case "my_field6": case "my_field6":
myField6Mapper = m; myField6Mapper = m;
break; break;
case "my_field7":
myField7Mapper = m;
break;
} }
} }
assertNotNull(myField1Mapper); assertNotNull(myField1Mapper);
@ -502,6 +510,10 @@ public class DynamicMappingTests extends ESSingleNodeTestCase {
assertTrue(myField6Mapper instanceof DateFieldMapper); assertTrue(myField6Mapper instanceof DateFieldMapper);
assertFalse(((DateFieldType) ((DateFieldMapper) myField6Mapper).fieldType()).hasDocValues()); assertFalse(((DateFieldType) ((DateFieldMapper) myField6Mapper).fieldType()).hasDocValues());
assertNotNull(myField7Mapper);
assertTrue(myField7Mapper instanceof BooleanFieldMapper);
assertFalse(((BooleanFieldType) ((BooleanFieldMapper) myField7Mapper).fieldType()).hasDocValues());
// This can't work // This can't work
try { try {
parse(newMapper, indexService.mapperService().documentMapperParser(), parse(newMapper, indexService.mapperService().documentMapperParser(),