move dynamic tempaltes to only allow to be defined on root object mapping (so easily reusable and simpler merging) #397.

This commit is contained in:
kimchy 2010-10-14 12:25:32 +02:00
parent 1578da404c
commit ad01f19db8
9 changed files with 290 additions and 125 deletions

View File

@ -22,7 +22,6 @@ package org.elasticsearch.index.mapper.xcontent;
import org.elasticsearch.ElasticSearchIllegalStateException;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.collect.ImmutableMap;
import org.elasticsearch.common.collect.Lists;
import org.elasticsearch.common.joda.FormatDateTimeFormatter;
import org.elasticsearch.common.joda.Joda;
import org.elasticsearch.common.util.concurrent.ThreadSafe;
@ -31,7 +30,6 @@ import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.index.mapper.*;
import java.io.IOException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@ -62,87 +60,73 @@ public class ObjectMapper implements XContentMapper, IncludeInAllMapper {
};
}
public static class Builder extends XContentMapper.Builder<Builder, ObjectMapper> {
public static class Builder<T extends Builder, Y extends ObjectMapper> extends XContentMapper.Builder<T, Y> {
private boolean enabled = Defaults.ENABLED;
protected boolean enabled = Defaults.ENABLED;
private boolean dynamic = Defaults.DYNAMIC;
protected boolean dynamic = Defaults.DYNAMIC;
private ContentPath.Type pathType = Defaults.PATH_TYPE;
protected ContentPath.Type pathType = Defaults.PATH_TYPE;
private List<FormatDateTimeFormatter> dateTimeFormatters = newArrayList();
protected List<FormatDateTimeFormatter> dateTimeFormatters = newArrayList();
private Boolean includeInAll;
protected Boolean includeInAll;
private final List<XContentMapper.Builder> mappersBuilders = newArrayList();
private final List<DynamicTemplate> dynamicTemplates = newArrayList();
protected final List<XContentMapper.Builder> mappersBuilders = newArrayList();
public Builder(String name) {
super(name);
this.builder = this;
this.builder = (T) this;
}
public Builder enabled(boolean enabled) {
public T enabled(boolean enabled) {
this.enabled = enabled;
return this;
return builder;
}
public Builder dynamic(boolean dynamic) {
public T dynamic(boolean dynamic) {
this.dynamic = dynamic;
return this;
return builder;
}
public Builder pathType(ContentPath.Type pathType) {
public T pathType(ContentPath.Type pathType) {
this.pathType = pathType;
return this;
return builder;
}
public Builder noDateTimeFormatter() {
public T noDateTimeFormatter() {
this.dateTimeFormatters = null;
return this;
return builder;
}
public Builder includeInAll(boolean includeInAll) {
public T includeInAll(boolean includeInAll) {
this.includeInAll = includeInAll;
return this;
return builder;
}
public Builder dateTimeFormatter(Iterable<FormatDateTimeFormatter> dateTimeFormatters) {
public T dateTimeFormatter(Iterable<FormatDateTimeFormatter> dateTimeFormatters) {
for (FormatDateTimeFormatter dateTimeFormatter : dateTimeFormatters) {
this.dateTimeFormatters.add(dateTimeFormatter);
}
return this;
return builder;
}
public Builder dateTimeFormatter(FormatDateTimeFormatter[] dateTimeFormatters) {
public T dateTimeFormatter(FormatDateTimeFormatter[] dateTimeFormatters) {
this.dateTimeFormatters.addAll(newArrayList(dateTimeFormatters));
return this;
return builder;
}
public Builder dateTimeFormatter(FormatDateTimeFormatter dateTimeFormatter) {
public T dateTimeFormatter(FormatDateTimeFormatter dateTimeFormatter) {
this.dateTimeFormatters.add(dateTimeFormatter);
return this;
return builder;
}
public Builder add(DynamicTemplate dynamicTemplate) {
this.dynamicTemplates.add(dynamicTemplate);
return this;
}
public Builder add(DynamicTemplate... dynamicTemplate) {
for (DynamicTemplate template : dynamicTemplate) {
this.dynamicTemplates.add(template);
}
return this;
}
public Builder add(XContentMapper.Builder builder) {
public T add(XContentMapper.Builder builder) {
mappersBuilders.add(builder);
return this;
return this.builder;
}
@Override public ObjectMapper build(BuilderContext context) {
@Override public Y build(BuilderContext context) {
if (dateTimeFormatters == null) {
dateTimeFormatters = newArrayList();
} else if (dateTimeFormatters.isEmpty()) {
@ -158,23 +142,27 @@ public class ObjectMapper implements XContentMapper, IncludeInAllMapper {
XContentMapper mapper = builder.build(context);
mappers.put(mapper.name(), mapper);
}
ObjectMapper objectMapper = new ObjectMapper(name, enabled, dynamic, pathType,
dateTimeFormatters.toArray(new FormatDateTimeFormatter[dateTimeFormatters.size()]),
mappers, dynamicTemplates.toArray(new DynamicTemplate[dynamicTemplates.size()]));
ObjectMapper objectMapper = createMapper(name, enabled, dynamic, pathType,
dateTimeFormatters.toArray(new FormatDateTimeFormatter[dateTimeFormatters.size()]), mappers);
context.path().pathType(origPathType);
context.path().remove();
objectMapper.includeInAll(includeInAll);
return objectMapper;
return (Y) objectMapper;
}
protected ObjectMapper createMapper(String name, boolean enabled, boolean dynamic, ContentPath.Type pathType,
FormatDateTimeFormatter[] dateTimeFormatters, Map<String, XContentMapper> mappers) {
return new ObjectMapper(name, enabled, dynamic, pathType, dateTimeFormatters, mappers);
}
}
public static class TypeParser implements XContentMapper.TypeParser {
@Override public XContentMapper.Builder parse(String name, Map<String, Object> node, ParserContext parserContext) throws MapperParsingException {
Map<String, Object> objectNode = node;
ObjectMapper.Builder builder = object(name);
ObjectMapper.Builder builder = createBuilder(name);
for (Map.Entry<String, Object> entry : objectNode.entrySet()) {
String fieldName = Strings.toUnderscoreCase(entry.getKey());
@ -187,19 +175,6 @@ public class ObjectMapper implements XContentMapper, IncludeInAllMapper {
if (!type.equals("object")) {
throw new MapperParsingException("Trying to parse an object but has a different type [" + type + "] for [" + name + "]");
}
} else if (fieldName.equals("dynamic_templates")) {
// "dynamic_templates" : [
// {
// "match" : "*_test",
// "match_mapping_type" : "string",
// "mapping" : { "type" : "string", "store" : "yes" }
// }
// ]
List tmplNodes = (List) fieldNode;
for (Object tmplNode : tmplNodes) {
Map<String, Object> tmpl = (Map<String, Object>) tmplNode;
builder.add(DynamicTemplate.parse(tmpl));
}
} else if (fieldName.equals("date_formats")) {
List<FormatDateTimeFormatter> dateTimeFormatters = newArrayList();
if (fieldNode instanceof List) {
@ -224,6 +199,8 @@ public class ObjectMapper implements XContentMapper, IncludeInAllMapper {
parseProperties(builder, (Map<String, Object>) fieldNode, parserContext);
} else if (fieldName.equals("include_in_all")) {
builder.includeInAll(nodeBooleanValue(fieldNode));
} else {
processField(builder, fieldName, fieldNode);
}
}
return builder;
@ -256,6 +233,14 @@ public class ObjectMapper implements XContentMapper, IncludeInAllMapper {
objBuilder.add(typeParser.parse(propName, propNode, parserContext));
}
}
protected Builder createBuilder(String name) {
return object(name);
}
protected void processField(Builder builder, String fieldName, Object fieldNode) {
}
}
private final String name;
@ -272,8 +257,6 @@ public class ObjectMapper implements XContentMapper, IncludeInAllMapper {
private volatile ImmutableMap<String, XContentMapper> mappers = ImmutableMap.of();
private volatile DynamicTemplate dynamicTemplates[];
private final Object mutex = new Object();
protected ObjectMapper(String name) {
@ -286,17 +269,16 @@ public class ObjectMapper implements XContentMapper, IncludeInAllMapper {
protected ObjectMapper(String name, boolean enabled, boolean dynamic, ContentPath.Type pathType,
FormatDateTimeFormatter[] dateTimeFormatters) {
this(name, enabled, dynamic, pathType, dateTimeFormatters, null, null);
this(name, enabled, dynamic, pathType, dateTimeFormatters, null);
}
ObjectMapper(String name, boolean enabled, boolean dynamic, ContentPath.Type pathType,
FormatDateTimeFormatter[] dateTimeFormatters, Map<String, XContentMapper> mappers, DynamicTemplate dynamicTemplates[]) {
FormatDateTimeFormatter[] dateTimeFormatters, Map<String, XContentMapper> mappers) {
this.name = name;
this.enabled = enabled;
this.dynamic = dynamic;
this.pathType = pathType;
this.dateTimeFormatters = dateTimeFormatters;
this.dynamicTemplates = dynamicTemplates == null ? new DynamicTemplate[0] : dynamicTemplates;
if (mappers != null) {
this.mappers = copyOf(mappers);
}
@ -401,10 +383,9 @@ public class ObjectMapper implements XContentMapper, IncludeInAllMapper {
objectMapper.parse(context);
} else {
BuilderContext builderContext = new BuilderContext(context.path());
XContentMapper.Builder builder = findTemplateBuilder(context, currentFieldName, "object");
XContentMapper.Builder builder = context.root().findTemplateBuilder(context, currentFieldName, "object");
if (builder == null) {
builder = XContentMapperBuilders.object(currentFieldName).enabled(true)
.add(dynamicTemplates)
.dynamic(dynamic).pathType(pathType).dateTimeFormatter(dateTimeFormatters);
}
objectMapper = builder.build(builderContext);
@ -474,7 +455,7 @@ public class ObjectMapper implements XContentMapper, IncludeInAllMapper {
for (FormatDateTimeFormatter dateTimeFormatter : dateTimeFormatters) {
try {
dateTimeFormatter.parser().parseMillis(text);
XContentMapper.Builder builder = findTemplateBuilder(context, currentFieldName, "date");
XContentMapper.Builder builder = context.root().findTemplateBuilder(context, currentFieldName, "date");
if (builder == null) {
builder = dateField(currentFieldName).dateTimeFormatter(dateTimeFormatter);
}
@ -487,7 +468,7 @@ public class ObjectMapper implements XContentMapper, IncludeInAllMapper {
}
}
if (!isDate) {
XContentMapper.Builder builder = findTemplateBuilder(context, currentFieldName, "string");
XContentMapper.Builder builder = context.root().findTemplateBuilder(context, currentFieldName, "string");
if (builder == null) {
builder = stringField(currentFieldName);
}
@ -497,53 +478,53 @@ public class ObjectMapper implements XContentMapper, IncludeInAllMapper {
XContentParser.NumberType numberType = context.parser().numberType();
if (numberType == XContentParser.NumberType.INT) {
if (context.parser().estimatedNumberType()) {
XContentMapper.Builder builder = findTemplateBuilder(context, currentFieldName, "long");
XContentMapper.Builder builder = context.root().findTemplateBuilder(context, currentFieldName, "long");
if (builder == null) {
builder = longField(currentFieldName);
}
mapper = builder.build(builderContext);
} else {
XContentMapper.Builder builder = findTemplateBuilder(context, currentFieldName, "integer");
XContentMapper.Builder builder = context.root().findTemplateBuilder(context, currentFieldName, "integer");
if (builder == null) {
builder = integerField(currentFieldName);
}
mapper = builder.build(builderContext);
}
} else if (numberType == XContentParser.NumberType.LONG) {
XContentMapper.Builder builder = findTemplateBuilder(context, currentFieldName, "long");
XContentMapper.Builder builder = context.root().findTemplateBuilder(context, currentFieldName, "long");
if (builder == null) {
builder = longField(currentFieldName);
}
mapper = builder.build(builderContext);
} else if (numberType == XContentParser.NumberType.FLOAT) {
if (context.parser().estimatedNumberType()) {
XContentMapper.Builder builder = findTemplateBuilder(context, currentFieldName, "double");
XContentMapper.Builder builder = context.root().findTemplateBuilder(context, currentFieldName, "double");
if (builder == null) {
builder = doubleField(currentFieldName);
}
mapper = builder.build(builderContext);
} else {
XContentMapper.Builder builder = findTemplateBuilder(context, currentFieldName, "float");
XContentMapper.Builder builder = context.root().findTemplateBuilder(context, currentFieldName, "float");
if (builder == null) {
builder = floatField(currentFieldName);
}
mapper = builder.build(builderContext);
}
} else if (numberType == XContentParser.NumberType.DOUBLE) {
XContentMapper.Builder builder = findTemplateBuilder(context, currentFieldName, "double");
XContentMapper.Builder builder = context.root().findTemplateBuilder(context, currentFieldName, "double");
if (builder == null) {
builder = doubleField(currentFieldName);
}
mapper = builder.build(builderContext);
}
} else if (token == XContentParser.Token.VALUE_BOOLEAN) {
XContentMapper.Builder builder = findTemplateBuilder(context, currentFieldName, "boolean");
XContentMapper.Builder builder = context.root().findTemplateBuilder(context, currentFieldName, "boolean");
if (builder == null) {
builder = booleanField(currentFieldName);
}
mapper = builder.build(builderContext);
} else {
XContentMapper.Builder builder = findTemplateBuilder(context, currentFieldName, null);
XContentMapper.Builder builder = context.root().findTemplateBuilder(context, currentFieldName, null);
if (builder != null) {
mapper = builder.build(builderContext);
} else {
@ -563,43 +544,15 @@ public class ObjectMapper implements XContentMapper, IncludeInAllMapper {
}
}
private XContentMapper.Builder findTemplateBuilder(ParseContext context, String name, String dynamicType) {
DynamicTemplate dynamicTemplate = findTemplate(name, dynamicType);
if (dynamicTemplate == null) {
return null;
}
XContentMapper.TypeParser.ParserContext parserContext = context.docMapperParser().parserContext();
return parserContext.typeParser(dynamicTemplate.mappingType(dynamicType)).parse(name, dynamicTemplate.mappingForName(name, dynamicType), parserContext);
}
private DynamicTemplate findTemplate(String name, String dynamicType) {
for (DynamicTemplate dynamicTemplate : dynamicTemplates) {
if (dynamicTemplate.match(name, dynamicType)) {
return dynamicTemplate;
}
}
return null;
}
@Override public void merge(XContentMapper mergeWith, MergeContext mergeContext) throws MergeMappingException {
if (!(mergeWith instanceof ObjectMapper)) {
mergeContext.addConflict("Can't merge a non object mapping [" + mergeWith.name() + "] with an object mapping [" + name() + "]");
return;
}
ObjectMapper mergeWithObject = (ObjectMapper) mergeWith;
if (!mergeContext.mergeFlags().simulate()) {
// merge them
List<DynamicTemplate> mergedTemplates = Lists.newArrayList(Arrays.asList(this.dynamicTemplates));
for (DynamicTemplate template : mergeWithObject.dynamicTemplates) {
int index = mergedTemplates.indexOf(template);
if (index == -1) {
mergedTemplates.add(template);
} else {
mergedTemplates.set(index, template);
}
}
this.dynamicTemplates = mergedTemplates.toArray(new DynamicTemplate[mergedTemplates.size()]);
}
doMerge(mergeWithObject, mergeContext);
synchronized (mutex) {
for (XContentMapper mergeWithMapper : mergeWithObject.mappers.values()) {
XContentMapper mergeIntoMapper = mappers.get(mergeWithMapper.name());
@ -632,6 +585,10 @@ public class ObjectMapper implements XContentMapper, IncludeInAllMapper {
}
}
protected void doMerge(ObjectMapper mergeWith, MergeContext mergeContext) {
}
@Override public void toXContent(XContentBuilder builder, Params params) throws IOException {
toXContent(builder, params, XContentMapper.EMPTY_ARRAY);
}
@ -645,13 +602,8 @@ public class ObjectMapper implements XContentMapper, IncludeInAllMapper {
if (includeInAll != null) {
builder.field("include_in_all", includeInAll);
}
if (dynamicTemplates != null && dynamicTemplates.length > 0) {
builder.startArray("dynamic_templates");
for (DynamicTemplate dynamicTemplate : dynamicTemplates) {
builder.map(dynamicTemplate.conf());
}
builder.endArray();
}
doXContent(builder, params);
if (dateTimeFormatters.length > 0) {
builder.startArray("date_formats");
@ -684,4 +636,8 @@ public class ObjectMapper implements XContentMapper, IncludeInAllMapper {
}
builder.endObject();
}
protected void doXContent(XContentBuilder builder, Params params) throws IOException {
}
}

View File

@ -124,6 +124,10 @@ public class ParseContext {
return this.document;
}
public RootObjectMapper root() {
return docMapper.root();
}
public XContentDocumentMapper docMapper() {
return this.docMapper;
}

View File

@ -0,0 +1,141 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search 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.index.mapper.xcontent;
import org.elasticsearch.common.collect.Lists;
import org.elasticsearch.common.joda.FormatDateTimeFormatter;
import org.elasticsearch.common.xcontent.XContentBuilder;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import static org.elasticsearch.common.collect.Lists.*;
/**
* @author kimchy (shay.banon)
*/
public class RootObjectMapper extends ObjectMapper {
public static class Builder extends ObjectMapper.Builder<Builder, RootObjectMapper> {
protected final List<DynamicTemplate> dynamicTemplates = newArrayList();
public Builder(String name) {
super(name);
this.builder = this;
}
public Builder add(DynamicTemplate dynamicTemplate) {
this.dynamicTemplates.add(dynamicTemplate);
return this;
}
public Builder add(DynamicTemplate... dynamicTemplate) {
for (DynamicTemplate template : dynamicTemplate) {
this.dynamicTemplates.add(template);
}
return this;
}
@Override protected ObjectMapper createMapper(String name, boolean enabled, boolean dynamic, ContentPath.Type pathType, FormatDateTimeFormatter[] dateTimeFormatters, Map<String, XContentMapper> mappers) {
return new RootObjectMapper(name, enabled, dynamic, pathType, dateTimeFormatters, mappers, dynamicTemplates.toArray(new DynamicTemplate[dynamicTemplates.size()]));
}
}
public static class TypeParser extends ObjectMapper.TypeParser {
@Override protected ObjectMapper.Builder createBuilder(String name) {
return new Builder(name);
}
@Override protected void processField(ObjectMapper.Builder builder, String fieldName, Object fieldNode) {
if (fieldName.equals("dynamic_templates")) {
// "dynamic_templates" : [
// {
// "match" : "*_test",
// "match_mapping_type" : "string",
// "mapping" : { "type" : "string", "store" : "yes" }
// }
// ]
List tmplNodes = (List) fieldNode;
for (Object tmplNode : tmplNodes) {
Map<String, Object> tmpl = (Map<String, Object>) tmplNode;
((Builder) builder).add(DynamicTemplate.parse(tmpl));
}
}
}
}
private volatile DynamicTemplate dynamicTemplates[];
RootObjectMapper(String name, boolean enabled, boolean dynamic, ContentPath.Type pathType,
FormatDateTimeFormatter[] dateTimeFormatters, Map<String, XContentMapper> mappers, DynamicTemplate dynamicTemplates[]) {
super(name, enabled, dynamic, pathType, dateTimeFormatters, mappers);
this.dynamicTemplates = dynamicTemplates;
}
public XContentMapper.Builder findTemplateBuilder(ParseContext context, String name, String dynamicType) {
DynamicTemplate dynamicTemplate = findTemplate(name, dynamicType);
if (dynamicTemplate == null) {
return null;
}
XContentMapper.TypeParser.ParserContext parserContext = context.docMapperParser().parserContext();
return parserContext.typeParser(dynamicTemplate.mappingType(dynamicType)).parse(name, dynamicTemplate.mappingForName(name, dynamicType), parserContext);
}
public DynamicTemplate findTemplate(String name, String dynamicType) {
for (DynamicTemplate dynamicTemplate : dynamicTemplates) {
if (dynamicTemplate.match(name, dynamicType)) {
return dynamicTemplate;
}
}
return null;
}
@Override protected void doMerge(ObjectMapper mergeWith, MergeContext mergeContext) {
RootObjectMapper mergeWithObject = (RootObjectMapper) mergeWith;
if (!mergeContext.mergeFlags().simulate()) {
// merge them
List<DynamicTemplate> mergedTemplates = Lists.newArrayList(Arrays.asList(this.dynamicTemplates));
for (DynamicTemplate template : mergeWithObject.dynamicTemplates) {
int index = mergedTemplates.indexOf(template);
if (index == -1) {
mergedTemplates.add(template);
} else {
mergedTemplates.set(index, template);
}
}
this.dynamicTemplates = mergedTemplates.toArray(new DynamicTemplate[mergedTemplates.size()]);
}
}
@Override protected void doXContent(XContentBuilder builder, Params params) throws IOException {
if (dynamicTemplates != null && dynamicTemplates.length > 0) {
builder.startArray("dynamic_templates");
for (DynamicTemplate dynamicTemplate : dynamicTemplates) {
builder.map(dynamicTemplate.conf());
}
builder.endArray();
}
}
}

View File

@ -64,13 +64,13 @@ public class XContentDocumentMapper implements DocumentMapper, ToXContent {
private final String index;
private final ObjectMapper rootObjectMapper;
private final RootObjectMapper rootObjectMapper;
private ImmutableMap<String, Object> attributes = ImmutableMap.of();
private XContentMapper.BuilderContext builderContext = new XContentMapper.BuilderContext(new ContentPath(1));
public Builder(String index, ObjectMapper.Builder builder) {
public Builder(String index, RootObjectMapper.Builder builder) {
this.index = index;
this.rootObjectMapper = builder.build(builderContext);
}
@ -171,7 +171,7 @@ public class XContentDocumentMapper implements DocumentMapper, ToXContent {
private final AllFieldMapper allFieldMapper;
private final ObjectMapper rootObjectMapper;
private final RootObjectMapper rootObjectMapper;
private final Analyzer indexAnalyzer;
@ -186,7 +186,7 @@ public class XContentDocumentMapper implements DocumentMapper, ToXContent {
private final Object mutex = new Object();
public XContentDocumentMapper(String index, XContentDocumentMapperParser docMapperParser,
ObjectMapper rootObjectMapper,
RootObjectMapper rootObjectMapper,
ImmutableMap<String, Object> attributes,
UidFieldMapper uidFieldMapper,
IdFieldMapper idFieldMapper,
@ -260,6 +260,10 @@ public class XContentDocumentMapper implements DocumentMapper, ToXContent {
return this.mappingSource;
}
public RootObjectMapper root() {
return this.rootObjectMapper;
}
@Override public org.elasticsearch.index.mapper.UidFieldMapper uidMapper() {
return this.uidFieldMapper;
}

View File

@ -53,7 +53,7 @@ public class XContentDocumentMapperParser extends AbstractIndexComponent impleme
private final AnalysisService analysisService;
private final ObjectMapper.TypeParser rootObjectTypeParser = new ObjectMapper.TypeParser();
private final RootObjectMapper.TypeParser rootObjectTypeParser = new RootObjectMapper.TypeParser();
private final Object typeParsersMutex = new Object();
@ -127,7 +127,7 @@ public class XContentDocumentMapperParser extends AbstractIndexComponent impleme
XContentMapper.TypeParser.ParserContext parserContext = new XContentMapper.TypeParser.ParserContext(analysisService, typeParsers);
XContentDocumentMapper.Builder docBuilder = doc(index.name(), (ObjectMapper.Builder) rootObjectTypeParser.parse(type, mapping, parserContext));
XContentDocumentMapper.Builder docBuilder = doc(index.name(), (RootObjectMapper.Builder) rootObjectTypeParser.parse(type, mapping, parserContext));
for (Map.Entry<String, Object> entry : mapping.entrySet()) {
String fieldName = Strings.toUnderscoreCase(entry.getKey());

View File

@ -28,7 +28,7 @@ public final class XContentMapperBuilders {
}
public static XContentDocumentMapper.Builder doc(String index, ObjectMapper.Builder objectBuilder) {
public static XContentDocumentMapper.Builder doc(String index, RootObjectMapper.Builder objectBuilder) {
return new XContentDocumentMapper.Builder(index, objectBuilder);
}
@ -64,6 +64,10 @@ public final class XContentMapperBuilders {
return new MultiFieldMapper.Builder(name);
}
public static RootObjectMapper.Builder rootObject(String name) {
return new RootObjectMapper.Builder(name);
}
public static ObjectMapper.Builder object(String name) {
return new ObjectMapper.Builder(name);
}

View File

@ -86,4 +86,59 @@ public class SimpleDynamicTemplatesTests {
fieldMappers = docMapper.mappers().fullName("multi2.org");
assertThat(fieldMappers.mappers().size(), equalTo(1));
}
@Test public void testSimpleWithXContentTraverse() throws Exception {
String mapping = copyToStringFromClasspath("/org/elasticsearch/index/mapper/xcontent/dynamictemplate/simple/test-mapping.json");
XContentDocumentMapper docMapper = MapperTests.newParser().parse(mapping);
docMapper.refreshSource();
docMapper = MapperTests.newParser().parse(docMapper.mappingSource().string());
byte[] json = copyToBytesFromClasspath("/org/elasticsearch/index/mapper/xcontent/dynamictemplate/simple/test-data.json");
Document doc = docMapper.parse(json).doc();
Field f = doc.getField("name");
assertThat(f.name(), equalTo("name"));
assertThat(f.stringValue(), equalTo("some name"));
assertThat(f.isIndexed(), equalTo(true));
assertThat(f.isTokenized(), equalTo(false));
FieldMappers fieldMappers = docMapper.mappers().fullName("name");
assertThat(fieldMappers.mappers().size(), equalTo(1));
f = doc.getField("multi1");
assertThat(f.name(), equalTo("multi1"));
assertThat(f.stringValue(), equalTo("multi 1"));
assertThat(f.isIndexed(), equalTo(true));
assertThat(f.isTokenized(), equalTo(true));
fieldMappers = docMapper.mappers().fullName("multi1");
assertThat(fieldMappers.mappers().size(), equalTo(1));
f = doc.getField("multi1.org");
assertThat(f.name(), equalTo("multi1.org"));
assertThat(f.stringValue(), equalTo("multi 1"));
assertThat(f.isIndexed(), equalTo(true));
assertThat(f.isTokenized(), equalTo(false));
fieldMappers = docMapper.mappers().fullName("multi1.org");
assertThat(fieldMappers.mappers().size(), equalTo(1));
f = doc.getField("multi2");
assertThat(f.name(), equalTo("multi2"));
assertThat(f.stringValue(), equalTo("multi 2"));
assertThat(f.isIndexed(), equalTo(true));
assertThat(f.isTokenized(), equalTo(true));
fieldMappers = docMapper.mappers().fullName("multi2");
assertThat(fieldMappers.mappers().size(), equalTo(1));
f = doc.getField("multi2.org");
assertThat(f.name(), equalTo("multi2.org"));
assertThat(f.stringValue(), equalTo("multi 2"));
assertThat(f.isIndexed(), equalTo(true));
assertThat(f.isTokenized(), equalTo(false));
fieldMappers = docMapper.mappers().fullName("multi2.org");
assertThat(fieldMappers.mappers().size(), equalTo(1));
}
}

View File

@ -71,7 +71,8 @@ public class MultiFieldTests {
@Test public void testBuildThenParse() throws Exception {
XContentDocumentMapperParser mapperParser = MapperTests.newParser();
XContentDocumentMapper builderDocMapper = doc("test", object("person").add(
XContentDocumentMapper builderDocMapper = doc("test", rootObject("person").add(
multiField("name")
.add(stringField("name").store(Field.Store.YES))
.add(stringField("indexed").index(Field.Index.ANALYZED))

View File

@ -41,7 +41,7 @@ public class SimpleMapperTests {
@Test public void testSimpleMapper() throws Exception {
XContentDocumentMapperParser mapperParser = MapperTests.newParser();
XContentDocumentMapper docMapper = doc("test",
object("person")
rootObject("person")
.add(object("name").add(stringField("first").store(YES).index(Field.Index.NO)))
).sourceField(source()).build(mapperParser);