diff --git a/.idea/dictionaries/kimchy.xml b/.idea/dictionaries/kimchy.xml index 9d24bb5f29a..2574bef590f 100644 --- a/.idea/dictionaries/kimchy.xml +++ b/.idea/dictionaries/kimchy.xml @@ -95,6 +95,7 @@ queryparser rackspace rebalance + reparse retrans retval rsts diff --git a/modules/elasticsearch/src/main/java/org/elasticsearch/cluster/metadata/MetaDataMappingService.java b/modules/elasticsearch/src/main/java/org/elasticsearch/cluster/metadata/MetaDataMappingService.java index 92cbdd02a0c..7f855523f2c 100644 --- a/modules/elasticsearch/src/main/java/org/elasticsearch/cluster/metadata/MetaDataMappingService.java +++ b/modules/elasticsearch/src/main/java/org/elasticsearch/cluster/metadata/MetaDataMappingService.java @@ -147,7 +147,7 @@ public class MetaDataMappingService extends AbstractComponent { } else if (!mappingType.equals(newMappers.values().iterator().next().type())) { throw new InvalidTypeNameException("Type name provided does not match type name within mapping definition"); } - if (mappingType.charAt(0) == '_') { + if (!MapperService.DEFAULT_MAPPING.equals(mappingType) && mappingType.charAt(0) == '_') { throw new InvalidTypeNameException("Document mapping type name can't start with '_'"); } diff --git a/modules/elasticsearch/src/main/java/org/elasticsearch/common/xcontent/XContentMerger.java b/modules/elasticsearch/src/main/java/org/elasticsearch/common/xcontent/XContentMerger.java new file mode 100644 index 00000000000..f1acc1efe3d --- /dev/null +++ b/modules/elasticsearch/src/main/java/org/elasticsearch/common/xcontent/XContentMerger.java @@ -0,0 +1,46 @@ +/* + * 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.common.xcontent; + +import java.util.Map; + +/** + * @author kimchy (shay.banon) + */ +public class XContentMerger { + + /** + * Merges the defaults provided as the second parameter into the content of the first. Only does recursive merge + * for inner maps. + */ + @SuppressWarnings({"unchecked"}) public static void mergeDefaults(Map content, Map defaults) { + for (Map.Entry defaultEntry : defaults.entrySet()) { + if (!content.containsKey(defaultEntry.getKey())) { + // copy it over, it does not exists in the content + content.put(defaultEntry.getKey(), defaultEntry.getValue()); + } else { + // in the content and in the default, only merge compound ones (maps) + if (content.get(defaultEntry.getKey()) instanceof Map && defaultEntry.getValue() instanceof Map) { + mergeDefaults((Map) content.get(defaultEntry.getKey()), (Map) defaultEntry.getValue()); + } + } + } + } +} diff --git a/modules/elasticsearch/src/main/java/org/elasticsearch/index/mapper/DocumentMapperParser.java b/modules/elasticsearch/src/main/java/org/elasticsearch/index/mapper/DocumentMapperParser.java index 853ec9f6d88..3e9555abaaa 100644 --- a/modules/elasticsearch/src/main/java/org/elasticsearch/index/mapper/DocumentMapperParser.java +++ b/modules/elasticsearch/src/main/java/org/elasticsearch/index/mapper/DocumentMapperParser.java @@ -26,6 +26,11 @@ import javax.annotation.Nullable; */ public interface DocumentMapperParser { + /** + * Parses the source mapping definition into a document mapper. + */ + DocumentMapper parse(String mappingSource) throws MapperParsingException; + /** * Parses the source mapping definition into a document mapper with the specified * type (overriding the one defined in the source mapping). @@ -33,7 +38,8 @@ public interface DocumentMapperParser { DocumentMapper parse(@Nullable String type, String mappingSource) throws MapperParsingException; /** - * Parses the source mapping definition into a document mapper. + * Parses the source mapping definition into a document mapper with the specified + * type (overriding the one defined in the source mapping). */ - DocumentMapper parse(String mappingSource) throws MapperParsingException; + DocumentMapper parse(@Nullable String type, String mappingSource, String defaultMappingSource) throws MapperParsingException; } diff --git a/modules/elasticsearch/src/main/java/org/elasticsearch/index/mapper/MapperService.java b/modules/elasticsearch/src/main/java/org/elasticsearch/index/mapper/MapperService.java index fd9b004d1ba..655c2cd807b 100644 --- a/modules/elasticsearch/src/main/java/org/elasticsearch/index/mapper/MapperService.java +++ b/modules/elasticsearch/src/main/java/org/elasticsearch/index/mapper/MapperService.java @@ -51,16 +51,14 @@ import static org.elasticsearch.common.collect.MapBuilder.*; @ThreadSafe public class MapperService extends AbstractIndexComponent implements Iterable { + public static final String DEFAULT_MAPPING = "_default_"; + /** * Will create types automatically if they do not exists in the repo yet */ private final boolean dynamic; - private final String dynamicMappingLocation; - - private final URL dynamicMappingUrl; - - private final String dynamicMappingSource; + private volatile String defaultMappingSource; private volatile ImmutableMap mappers = ImmutableMap.of(); @@ -74,7 +72,7 @@ public class MapperService extends AbstractIndexComponent implements Iterable iterator() { @@ -145,7 +134,7 @@ public class MapperService extends AbstractIndexComponent implements Iterable root; - XContentParser xContentParser = null; - try { - xContentParser = XContentFactory.xContent(source).createParser(source); - root = xContentParser.map(); - } catch (IOException e) { - throw new MapperParsingException("Failed to parse mapping definition", e); - } finally { - if (xContentParser != null) { - xContentParser.close(); - } + @Override public XContentDocumentMapper parse(@Nullable String type, String source) throws MapperParsingException { + return parse(type, source, null); + } + + @Override public XContentDocumentMapper parse(@Nullable String type, String source, String defaultSource) throws MapperParsingException { + Map mapping = null; + if (source != null) { + Tuple> t = extractMapping(type, source); + type = t.v1(); + mapping = t.v2(); } - String rootName = root.keySet().iterator().next(); - Map rootObj; + if (mapping == null) { + mapping = Maps.newHashMap(); + } + if (type == null) { - // we have no type, we assume the first node is the type - rootObj = (Map) root.get(rootName); - type = rootName; - } else { - // we have a type, check if the top level one is the type as well - // if it is, then the root is that node, if not then the root is the master node - if (type.equals(rootName)) { - Object tmpNode = root.get(type); - if (!(tmpNode instanceof Map)) { - throw new MapperParsingException("Expected root node name [" + rootName + "] to be of object type, but its not"); - } - rootObj = (Map) tmpNode; - } else if (rootName.equals("_default_")) { - Object tmpNode = root.get("_default_"); - if (!(tmpNode instanceof Map)) { - throw new MapperParsingException("_default_ mappings must have an inner object representing the actual mappings for the type"); - } - rootObj = (Map) tmpNode; - } else { - rootObj = root; + throw new MapperParsingException("Failed to derive type"); + } + + if (defaultSource != null) { + Tuple> t = extractMapping(MapperService.DEFAULT_MAPPING, defaultSource); + if (t.v2() != null) { + XContentMerger.mergeDefaults(mapping, t.v2()); } } - XContentTypeParser.ParserContext parserContext = new XContentTypeParser.ParserContext(rootObj, analysisService, typeParsers); + XContentTypeParser.ParserContext parserContext = new XContentTypeParser.ParserContext(mapping, analysisService, typeParsers); - XContentDocumentMapper.Builder docBuilder = doc((XContentObjectMapper.Builder) rootObjectTypeParser.parse(type, rootObj, parserContext)); + XContentDocumentMapper.Builder docBuilder = doc((XContentObjectMapper.Builder) rootObjectTypeParser.parse(type, mapping, parserContext)); - for (Map.Entry entry : rootObj.entrySet()) { + for (Map.Entry entry : mapping.entrySet()) { String fieldName = Strings.toUnderscoreCase(entry.getKey()); Object fieldNode = entry.getValue(); @@ -157,13 +147,11 @@ public class XContentDocumentMapperParser implements DocumentMapperParser { } ImmutableMap attributes = ImmutableMap.of(); - if (rootObj.containsKey("_attributes")) { - attributes = ImmutableMap.copyOf((Map) rootObj.get("_attributes")); + if (mapping.containsKey("_attributes")) { + attributes = ImmutableMap.copyOf((Map) mapping.get("_attributes")); } docBuilder.attributes(attributes); - docBuilder.mappingSource(source); - XContentDocumentMapper documentMapper = docBuilder.build(); // update the source with the generated one documentMapper.mappingSource(documentMapper.buildSource()); @@ -227,4 +215,31 @@ public class XContentDocumentMapperParser implements DocumentMapperParser { } return builder; } + + private Tuple> extractMapping(String type, String source) throws MapperParsingException { + Map root; + XContentParser xContentParser = null; + try { + xContentParser = XContentFactory.xContent(source).createParser(source); + root = xContentParser.map(); + } catch (IOException e) { + throw new MapperParsingException("Failed to parse mapping definition", e); + } finally { + if (xContentParser != null) { + xContentParser.close(); + } + } + + // we always assume the first and single key is the mapping type root + if (root.keySet().size() != 1) { + throw new MapperParsingException("Mapping must have the `type` as the root object"); + } + + String rootName = root.keySet().iterator().next(); + if (type == null) { + type = rootName; + } + + return new Tuple>(type, (Map) root.get(rootName)); + } } diff --git a/modules/elasticsearch/src/main/java/org/elasticsearch/index/mapper/xcontent/XContentObjectMapper.java b/modules/elasticsearch/src/main/java/org/elasticsearch/index/mapper/xcontent/XContentObjectMapper.java index 0e66f5c6683..af0efb2b14a 100644 --- a/modules/elasticsearch/src/main/java/org/elasticsearch/index/mapper/xcontent/XContentObjectMapper.java +++ b/modules/elasticsearch/src/main/java/org/elasticsearch/index/mapper/xcontent/XContentObjectMapper.java @@ -314,8 +314,16 @@ public class XContentObjectMapper implements XContentMapper, XContentIncludeInAl context.path().pathType(pathType); String currentFieldName = parser.currentName(); - XContentParser.Token token; - while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) { + XContentParser.Token token = parser.currentToken(); + // if we are at the end of the previous object, advance + if (token == XContentParser.Token.END_OBJECT) { + token = parser.nextToken(); + } + if (token == XContentParser.Token.START_OBJECT) { + // if we are just starting an OBJECT, advance, this is the object we are parsing, we need the name first + token = parser.nextToken(); + } + while (token != XContentParser.Token.END_OBJECT) { if (token == XContentParser.Token.START_OBJECT) { serializeObject(context, currentFieldName); } else if (token == XContentParser.Token.START_ARRAY) { @@ -324,9 +332,10 @@ public class XContentObjectMapper implements XContentMapper, XContentIncludeInAl currentFieldName = parser.currentName(); } else if (token == XContentParser.Token.VALUE_NULL) { serializeNullValue(context, currentFieldName); - } else { + } else if (token.isValue()) { serializeValue(context, currentFieldName, token); } + token = parser.nextToken(); } // restore the enable path flag context.path().pathType(origPathType); diff --git a/modules/elasticsearch/src/main/java/org/elasticsearch/index/mapper/xcontent/dynamic-mapping.json b/modules/elasticsearch/src/main/java/org/elasticsearch/index/mapper/xcontent/default-mapping.json similarity index 100% rename from modules/elasticsearch/src/main/java/org/elasticsearch/index/mapper/xcontent/dynamic-mapping.json rename to modules/elasticsearch/src/main/java/org/elasticsearch/index/mapper/xcontent/default-mapping.json diff --git a/modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/XContentMapperTests.java b/modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/XContentMapperTests.java new file mode 100644 index 00000000000..951ba1c75a3 --- /dev/null +++ b/modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/XContentMapperTests.java @@ -0,0 +1,40 @@ +/* + * 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.settings.ImmutableSettings; +import org.elasticsearch.env.Environment; +import org.elasticsearch.index.Index; +import org.elasticsearch.index.analysis.AnalysisService; +import org.elasticsearch.index.mapper.MapperService; + +/** + * @author kimchy (shay.banon) + */ +public class XContentMapperTests { + + public static XContentDocumentMapperParser newParser() { + return new XContentDocumentMapperParser(new AnalysisService(new Index("test"))); + } + + public static MapperService newMapperService() { + return new MapperService(new Index("test"), ImmutableSettings.Builder.EMPTY_SETTINGS, new Environment(), new AnalysisService(new Index("test"))); + } +} diff --git a/modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/all/SimpleAllMapperTests.java b/modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/all/SimpleAllMapperTests.java index bd00466bcb7..a8b6c9edc39 100644 --- a/modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/all/SimpleAllMapperTests.java +++ b/modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/all/SimpleAllMapperTests.java @@ -23,10 +23,8 @@ import org.apache.lucene.document.Document; import org.elasticsearch.common.lucene.all.AllEntries; import org.elasticsearch.common.lucene.all.AllField; import org.elasticsearch.common.lucene.all.AllTokenStream; -import org.elasticsearch.index.Index; -import org.elasticsearch.index.analysis.AnalysisService; import org.elasticsearch.index.mapper.xcontent.XContentDocumentMapper; -import org.elasticsearch.index.mapper.xcontent.XContentDocumentMapperParser; +import org.elasticsearch.index.mapper.xcontent.XContentMapperTests; import org.testng.annotations.Test; import static org.elasticsearch.common.io.Streams.*; @@ -41,7 +39,7 @@ public class SimpleAllMapperTests { @Test public void testSimpleAllMappers() throws Exception { String mapping = copyToStringFromClasspath("/org/elasticsearch/index/mapper/xcontent/all/mapping.json"); - XContentDocumentMapper docMapper = (XContentDocumentMapper) new XContentDocumentMapperParser(new AnalysisService(new Index("test"))).parse(mapping); + XContentDocumentMapper docMapper = XContentMapperTests.newParser().parse(mapping); byte[] json = copyToBytesFromClasspath("/org/elasticsearch/index/mapper/xcontent/all/test1.json"); Document doc = docMapper.parse(json).doc(); AllField field = (AllField) doc.getFieldable("_all"); @@ -53,11 +51,11 @@ public class SimpleAllMapperTests { @Test public void testSimpleAllMappersWithReparse() throws Exception { String mapping = copyToStringFromClasspath("/org/elasticsearch/index/mapper/xcontent/all/mapping.json"); - XContentDocumentMapper docMapper = (XContentDocumentMapper) new XContentDocumentMapperParser(new AnalysisService(new Index("test"))).parse(mapping); + XContentDocumentMapper docMapper = XContentMapperTests.newParser().parse(mapping); String builtMapping = docMapper.buildSource(); // System.out.println(builtMapping); // reparse it - XContentDocumentMapper builtDocMapper = (XContentDocumentMapper) new XContentDocumentMapperParser(new AnalysisService(new Index("test"))).parse(builtMapping); + XContentDocumentMapper builtDocMapper = XContentMapperTests.newParser().parse(builtMapping); byte[] json = copyToBytesFromClasspath("/org/elasticsearch/index/mapper/xcontent/all/test1.json"); Document doc = builtDocMapper.parse(json).doc(); @@ -70,7 +68,7 @@ public class SimpleAllMapperTests { @Test public void testSimpleAllMappersWithStore() throws Exception { String mapping = copyToStringFromClasspath("/org/elasticsearch/index/mapper/xcontent/all/store-mapping.json"); - XContentDocumentMapper docMapper = (XContentDocumentMapper) new XContentDocumentMapperParser(new AnalysisService(new Index("test"))).parse(mapping); + XContentDocumentMapper docMapper = XContentMapperTests.newParser().parse(mapping); byte[] json = copyToBytesFromClasspath("/org/elasticsearch/index/mapper/xcontent/all/test1.json"); Document doc = docMapper.parse(json).doc(); AllField field = (AllField) doc.getFieldable("_all"); @@ -85,11 +83,11 @@ public class SimpleAllMapperTests { @Test public void testSimpleAllMappersWithReparseWithStore() throws Exception { String mapping = copyToStringFromClasspath("/org/elasticsearch/index/mapper/xcontent/all/store-mapping.json"); - XContentDocumentMapper docMapper = (XContentDocumentMapper) new XContentDocumentMapperParser(new AnalysisService(new Index("test"))).parse(mapping); + XContentDocumentMapper docMapper = XContentMapperTests.newParser().parse(mapping); String builtMapping = docMapper.buildSource(); System.out.println(builtMapping); // reparse it - XContentDocumentMapper builtDocMapper = (XContentDocumentMapper) new XContentDocumentMapperParser(new AnalysisService(new Index("test"))).parse(builtMapping); + XContentDocumentMapper builtDocMapper = XContentMapperTests.newParser().parse(builtMapping); byte[] json = copyToBytesFromClasspath("/org/elasticsearch/index/mapper/xcontent/all/test1.json"); Document doc = builtDocMapper.parse(json).doc(); diff --git a/modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/all/mapping.json b/modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/all/mapping.json index e8b8697c9d1..657743a04a4 100644 --- a/modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/all/mapping.json +++ b/modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/all/mapping.json @@ -1,33 +1,33 @@ { - person : { - _all : {enabled : true}, - properties : { - name : { - type : "object", - dynamic : false, - properties : { - first : {type : "string", store : "yes", include_in_all : false}, - last : {type : "string", index : "not_analyzed"} + "person" : { + "_all" : {"enabled" : true}, + "properties" : { + "name" : { + "type" : "object", + "dynamic" : false, + "properties" : { + "first" : {"type" : "string", "store" : "yes", "include_in_all" : false}, + "last" : {"type" : "string", "index" : "not_analyzed"} } }, - address : { - type : "object", - include_in_all : false, - properties : { - first : { - properties : { - location : {type : "string", store : "yes", index_name : "firstLocation"} + "address" : { + "type" : "object", + "include_in_all" : false, + "properties" : { + "first" : { + "properties" : { + "location" : {"type" : "string", "store" : "yes", "index_name" : "firstLocation"} } }, - last : { - properties : { - location : {type : "string"} + "last" : { + "properties" : { + "location" : {"type" : "string"} } } } }, - simple1 : {type : "long", include_in_all : true}, - simple2 : {type : "long", include_in_all : false} + "simple1" : {"type" : "long", "include_in_all" : true}, + "simple2" : {"type" : "long", "include_in_all" : false} } } } \ No newline at end of file diff --git a/modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/all/store-mapping.json b/modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/all/store-mapping.json index 4ed84b785da..356d7ef3d29 100644 --- a/modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/all/store-mapping.json +++ b/modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/all/store-mapping.json @@ -1,33 +1,33 @@ { - person : { - _all : {enabled : true, store : "yes"}, - properties : { - name : { - type : "object", - dynamic : false, - properties : { - first : {type : "string", store : "yes", include_in_all : false}, - last : {type : "string", index : "not_analyzed"} + "person" : { + "_all" : {"enabled" : true, "store" : "yes"}, + "properties" : { + "name" : { + "type" : "object", + "dynamic" : false, + "properties" : { + "first" : {"type" : "string", "store" : "yes", "include_in_all" : false}, + "last" : {"type" : "string", "index" : "not_analyzed"} } }, - address : { - type : "object", - include_in_all : false, - properties : { - first : { - properties : { - location : {type : "string", store : "yes", index_name : "firstLocation"} + "address" : { + "type" : "object", + "include_in_all" : false, + "properties" : { + "first" : { + "properties" : { + "location" : {"type" : "string", "store" : "yes", "index_name" : "firstLocation"} } }, - last : { - properties : { - location : {type : "string"} + "last" : { + "properties" : { + "location" : {"type" : "string"} } } } }, - simple1 : {type : "long", include_in_all : true}, - simple2 : {type : "long", include_in_all : false} + "simple1" : {"type" : "long", "include_in_all" : true}, + "simple2" : {"type" : "long", "include_in_all" : false} } } } \ No newline at end of file diff --git a/modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/all/test1.json b/modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/all/test1.json index 8c5e43c1c5b..378b8a2df4a 100644 --- a/modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/all/test1.json +++ b/modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/all/test1.json @@ -1,20 +1,20 @@ { - person : { - _boost : 3.7, - _id : "1", - name : { - first : "shay", - last : "banon" + "person" : { + "_boost" : 3.7, + "_id" : "1", + "name" : { + "first" : "shay", + "last" : "banon" }, - address : { - first : { - location : "first location" + "address" : { + "first" : { + "location" : "first location" }, - last : { - location : "last location" + "last" : { + "location" : "last location" } }, - simple1 : 1, - simple2 : 2 + "simple1" : 1, + "simple2" : 2 } } \ No newline at end of file diff --git a/modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/defaultsource/DefaultSourceMappingTests.java b/modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/defaultsource/DefaultSourceMappingTests.java new file mode 100644 index 00000000000..137a3369947 --- /dev/null +++ b/modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/defaultsource/DefaultSourceMappingTests.java @@ -0,0 +1,101 @@ +/* + * 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.defaultsource; + +import org.elasticsearch.common.xcontent.XContentFactory; +import org.elasticsearch.common.xcontent.XContentType; +import org.elasticsearch.index.mapper.MapperParsingException; +import org.elasticsearch.index.mapper.MapperService; +import org.elasticsearch.index.mapper.xcontent.XContentDocumentMapper; +import org.elasticsearch.index.mapper.xcontent.XContentMapperTests; +import org.testng.annotations.Test; + +import static org.hamcrest.MatcherAssert.*; +import static org.hamcrest.Matchers.*; + +/** + * @author kimchy (shay.banon) + */ +public class DefaultSourceMappingTests { + + @Test public void testDefaultMappingAndNoMapping() throws Exception { + String defaultMapping = XContentFactory.contentTextBuilder(XContentType.JSON).startObject().startObject(MapperService.DEFAULT_MAPPING) + .startObject("_source").field("enabled", false).endObject() + .endObject().endObject().string(); + + XContentDocumentMapper mapper = XContentMapperTests.newParser().parse("my_type", null, defaultMapping); + assertThat(mapper.type(), equalTo("my_type")); + assertThat(mapper.sourceMapper().enabled(), equalTo(false)); + + try { + mapper = XContentMapperTests.newParser().parse(null, null, defaultMapping); + assertThat(mapper.type(), equalTo("my_type")); + assertThat(mapper.sourceMapper().enabled(), equalTo(false)); + assert false; + } catch (MapperParsingException e) { + // all is well + } + } + + @Test public void testDefaultMappingAndWithMappingOverride() throws Exception { + String defaultMapping = XContentFactory.contentTextBuilder(XContentType.JSON).startObject().startObject(MapperService.DEFAULT_MAPPING) + .startObject("_source").field("enabled", false).endObject() + .endObject().endObject().string(); + + String mapping = XContentFactory.contentTextBuilder(XContentType.JSON).startObject().startObject("type") + .startObject("_source").field("enabled", true).endObject() + .endObject().endObject().string(); + + XContentDocumentMapper mapper = XContentMapperTests.newParser().parse("my_type", mapping, defaultMapping); + assertThat(mapper.type(), equalTo("my_type")); + assertThat(mapper.sourceMapper().enabled(), equalTo(true)); + } + + @Test public void testDefaultMappingAndNoMappingWithMapperService() throws Exception { + String defaultMapping = XContentFactory.contentTextBuilder(XContentType.JSON).startObject().startObject(MapperService.DEFAULT_MAPPING) + .startObject("_source").field("enabled", false).endObject() + .endObject().endObject().string(); + + MapperService mapperService = XContentMapperTests.newMapperService(); + mapperService.add(MapperService.DEFAULT_MAPPING, defaultMapping); + + XContentDocumentMapper mapper = (XContentDocumentMapper) mapperService.type("my_type"); + assertThat(mapper.type(), equalTo("my_type")); + assertThat(mapper.sourceMapper().enabled(), equalTo(false)); + } + + @Test public void testDefaultMappingAndWithMappingOverrideWithMapperService() throws Exception { + String defaultMapping = XContentFactory.contentTextBuilder(XContentType.JSON).startObject().startObject(MapperService.DEFAULT_MAPPING) + .startObject("_source").field("enabled", false).endObject() + .endObject().endObject().string(); + + MapperService mapperService = XContentMapperTests.newMapperService(); + mapperService.add(MapperService.DEFAULT_MAPPING, defaultMapping); + + String mapping = XContentFactory.contentTextBuilder(XContentType.JSON).startObject().startObject("type") + .startObject("_source").field("enabled", true).endObject() + .endObject().endObject().string(); + mapperService.add("my_type", mapping); + + XContentDocumentMapper mapper = (XContentDocumentMapper) mapperService.type("my_type"); + assertThat(mapper.type(), equalTo("my_type")); + assertThat(mapper.sourceMapper().enabled(), equalTo(true)); + } +} diff --git a/modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/merge/test1/Test1MergeMapperTests.java b/modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/merge/test1/Test1MergeMapperTests.java index 9774e9c4534..e39a92ec360 100644 --- a/modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/merge/test1/Test1MergeMapperTests.java +++ b/modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/merge/test1/Test1MergeMapperTests.java @@ -19,11 +19,9 @@ package org.elasticsearch.index.mapper.xcontent.merge.test1; -import org.elasticsearch.index.Index; -import org.elasticsearch.index.analysis.AnalysisService; import org.elasticsearch.index.mapper.DocumentMapper; import org.elasticsearch.index.mapper.xcontent.XContentDocumentMapper; -import org.elasticsearch.index.mapper.xcontent.XContentDocumentMapperParser; +import org.elasticsearch.index.mapper.xcontent.XContentMapperTests; import org.testng.annotations.Test; import static org.elasticsearch.common.io.Streams.*; @@ -39,9 +37,9 @@ public class Test1MergeMapperTests { @Test public void test1Merge() throws Exception { String stage1Mapping = copyToStringFromClasspath("/org/elasticsearch/index/mapper/xcontent/merge/test1/stage1.json"); - XContentDocumentMapper stage1 = (XContentDocumentMapper) new XContentDocumentMapperParser(new AnalysisService(new Index("test"))).parse(stage1Mapping); + XContentDocumentMapper stage1 = XContentMapperTests.newParser().parse(stage1Mapping); String stage2Mapping = copyToStringFromClasspath("/org/elasticsearch/index/mapper/xcontent/merge/test1/stage2.json"); - XContentDocumentMapper stage2 = (XContentDocumentMapper) new XContentDocumentMapperParser(new AnalysisService(new Index("test"))).parse(stage2Mapping); + XContentDocumentMapper stage2 = XContentMapperTests.newParser().parse(stage2Mapping); DocumentMapper.MergeResult mergeResult = stage1.merge(stage2, mergeFlags().simulate(true)); assertThat(mergeResult.hasConflicts(), equalTo(false)); diff --git a/modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/multifield/XContentMultiFieldTests.java b/modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/multifield/XContentMultiFieldTests.java index ec7d74d6aa2..08c141e8d95 100644 --- a/modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/multifield/XContentMultiFieldTests.java +++ b/modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/multifield/XContentMultiFieldTests.java @@ -21,10 +21,8 @@ package org.elasticsearch.index.mapper.xcontent.multifield; import org.apache.lucene.document.Document; import org.apache.lucene.document.Field; -import org.elasticsearch.index.Index; -import org.elasticsearch.index.analysis.AnalysisService; import org.elasticsearch.index.mapper.xcontent.XContentDocumentMapper; -import org.elasticsearch.index.mapper.xcontent.XContentDocumentMapperParser; +import org.elasticsearch.index.mapper.xcontent.XContentMapperTests; import org.testng.annotations.Test; import static org.elasticsearch.common.io.Streams.*; @@ -40,7 +38,7 @@ public class XContentMultiFieldTests { @Test public void testMultiField() throws Exception { String mapping = copyToStringFromClasspath("/org/elasticsearch/index/mapper/xcontent/multifield/test-mapping.json"); - XContentDocumentMapper docMapper = (XContentDocumentMapper) new XContentDocumentMapperParser(new AnalysisService(new Index("test"))).parse(mapping); + XContentDocumentMapper docMapper = XContentMapperTests.newParser().parse(mapping); byte[] json = copyToBytesFromClasspath("/org/elasticsearch/index/mapper/xcontent/multifield/test-data.json"); Document doc = docMapper.parse(json).doc(); @@ -81,7 +79,7 @@ public class XContentMultiFieldTests { String builtMapping = builderDocMapper.buildSource(); // System.out.println(builtMapping); // reparse it - XContentDocumentMapper docMapper = (XContentDocumentMapper) new XContentDocumentMapperParser(new AnalysisService(new Index("test"))).parse(builtMapping); + XContentDocumentMapper docMapper = XContentMapperTests.newParser().parse(builtMapping); byte[] json = copyToBytesFromClasspath("/org/elasticsearch/index/mapper/xcontent/multifield/test-data.json"); diff --git a/modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/multifield/test-data.json b/modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/multifield/test-data.json index 4a1795da6b4..e3d73279543 100644 --- a/modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/multifield/test-data.json +++ b/modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/multifield/test-data.json @@ -1,7 +1,7 @@ { - _id : 1, - name : "some name", - object1 : { - multi1 : "2010-01-01" + "_id" : 1, + "name" : "some name", + "object1" : { + "multi1" : "2010-01-01" } } \ No newline at end of file diff --git a/modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/multifield/test-mapping.json b/modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/multifield/test-mapping.json index 489f80f4eb2..edce702ddc3 100644 --- a/modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/multifield/test-mapping.json +++ b/modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/multifield/test-mapping.json @@ -1,21 +1,21 @@ { - person : { - properties : { + "person" : { + "properties" : { "name" : { - type : "multi_field", + "type" : "multi_field", "fields" : { - "name" : {type: "string", index : "analyzed", store : "yes"}, - "indexed" : {type: "string", index : "analyzed"}, - "not_indexed" : {type: "string", index : "no", store : "yes"} + "name" : {"type": "string", "index" : "analyzed", "store" : "yes"}, + "indexed" : {"type": "string", "index" : "analyzed"}, + "not_indexed" : {"type": "string", "index" : "no", "store" : "yes"} } }, "object1" : { - properties : { + "properties" : { "multi1" : { - type : "multi_field", + "type" : "multi_field", "fields" : { - "multi1" : {type : "date"}, - "string" : {type: "string", index : "not_analyzed"} + "multi1" : {"type": "date"}, + "string" : {"type": "string", "index" : "not_analyzed"} } } } diff --git a/modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/overridetype/OverrideTypeMappingTests.java b/modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/overridetype/OverrideTypeMappingTests.java new file mode 100644 index 00000000000..4d04ffdee61 --- /dev/null +++ b/modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/overridetype/OverrideTypeMappingTests.java @@ -0,0 +1,49 @@ +/* + * 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.overridetype; + +import org.elasticsearch.common.xcontent.XContentFactory; +import org.elasticsearch.common.xcontent.XContentType; +import org.elasticsearch.index.mapper.xcontent.XContentDocumentMapper; +import org.elasticsearch.index.mapper.xcontent.XContentMapperTests; +import org.testng.annotations.Test; + +import static org.hamcrest.MatcherAssert.*; +import static org.hamcrest.Matchers.*; + +/** + * @author kimchy (shay.banon) + */ +public class OverrideTypeMappingTests { + + @Test public void testOverrideType() throws Exception { + String mapping = XContentFactory.contentTextBuilder(XContentType.JSON).startObject().startObject("type") + .startObject("_source").field("enabled", false).endObject() + .endObject().endObject().string(); + + XContentDocumentMapper mapper = XContentMapperTests.newParser().parse("my_type", mapping); + assertThat(mapper.type(), equalTo("my_type")); + assertThat(mapper.sourceMapper().enabled(), equalTo(false)); + + mapper = XContentMapperTests.newParser().parse(mapping); + assertThat(mapper.type(), equalTo("type")); + assertThat(mapper.sourceMapper().enabled(), equalTo(false)); + } +} diff --git a/modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/path/PathXContentMapperTests.java b/modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/path/PathXContentMapperTests.java index 38c7ca03844..94e8ac2db3d 100644 --- a/modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/path/PathXContentMapperTests.java +++ b/modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/path/PathXContentMapperTests.java @@ -19,10 +19,8 @@ package org.elasticsearch.index.mapper.xcontent.path; -import org.elasticsearch.index.Index; -import org.elasticsearch.index.analysis.AnalysisService; import org.elasticsearch.index.mapper.xcontent.XContentDocumentMapper; -import org.elasticsearch.index.mapper.xcontent.XContentDocumentMapperParser; +import org.elasticsearch.index.mapper.xcontent.XContentMapperTests; import org.testng.annotations.Test; import java.io.IOException; @@ -38,7 +36,7 @@ public class PathXContentMapperTests { @Test public void testPathMapping() throws IOException { String mapping = copyToStringFromClasspath("/org/elasticsearch/index/mapper/xcontent/path/test-mapping.json"); - XContentDocumentMapper docMapper = (XContentDocumentMapper) new XContentDocumentMapperParser(new AnalysisService(new Index("test"))).parse(mapping); + XContentDocumentMapper docMapper = XContentMapperTests.newParser().parse(mapping); assertThat(docMapper.mappers().indexName("first1"), notNullValue()); assertThat(docMapper.mappers().indexName("name1.first1"), nullValue()); diff --git a/modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/simple/SimpleXContentMapperTests.java b/modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/simple/SimpleXContentMapperTests.java index 364e99628ce..0f93b561636 100644 --- a/modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/simple/SimpleXContentMapperTests.java +++ b/modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/simple/SimpleXContentMapperTests.java @@ -91,19 +91,6 @@ public class SimpleXContentMapperTests { // System.out.println("Json: " + docMapper.sourceMapper().value(doc)); } - @Test public void testSimpleParserMappingWithNoType() throws Exception { - String mapping = copyToStringFromClasspath("/org/elasticsearch/index/mapper/xcontent/simple/test-mapping-notype.json"); - XContentDocumentMapper docMapper = (XContentDocumentMapper) new XContentDocumentMapperParser(new AnalysisService(new Index("test"))).parse("person", mapping); - byte[] json = copyToBytesFromClasspath("/org/elasticsearch/index/mapper/xcontent/simple/test1.json"); - Document doc = docMapper.parse(json).doc(); - assertThat(doc.get(docMapper.uidMapper().names().indexName()), equalTo(Uid.createUid("person", "1"))); - assertThat((double) doc.getBoost(), closeTo(3.7, 0.01)); - assertThat(doc.get(docMapper.mappers().name("first").mapper().names().indexName()), equalTo("shay")); - assertThat(doc.getFields(docMapper.idMapper().names().indexName()).length, equalTo(1)); -// System.out.println("Document: " + doc); -// System.out.println("Json: " + docMapper.sourceMapper().value(doc)); - } - @Test public void testSimpleParserNoTypeNoId() throws Exception { String mapping = copyToStringFromClasspath("/org/elasticsearch/index/mapper/xcontent/simple/test-mapping.json"); XContentDocumentMapper docMapper = (XContentDocumentMapper) new XContentDocumentMapperParser(new AnalysisService(new Index("test"))).parse(mapping); diff --git a/modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/simple/test-mapping-notype.json b/modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/simple/test-mapping-notype.json deleted file mode 100644 index 1a62b97657d..00000000000 --- a/modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/simple/test-mapping-notype.json +++ /dev/null @@ -1,52 +0,0 @@ -{ - date_formats : ["yyyy-MM-dd", "dd-MM-yyyy"], - dynamic : false, - enabled : true, - _id : {name : "_id", index_name : "_id"}, - _source : {name : "_source" }, - _type : {name : "_type"}, - _boost : {name : "_boost", null_value : 2.0}, - properties : { - name : { - type : "object", - dynamic : false, - properties : { - first : {type : "string", store : "yes"}, - last : {type : "string", index : "not_analyzed"} - } - }, - address : { - type : "object", - properties : { - first : { - properties : { - location : {type : "string", store : "yes", index_name : "firstLocation"} - } - }, - last : { - properties : { - location : {type : "string"} - } - } - } - }, - age : {type : "integer", null_value : 0}, - birthdate : {type : "date", format : "yyyy-MM-dd"}, - nerd : {type : "boolean"}, - dogs : {type : "string", index_name : "dog"}, - complex : { - type : "object", - properties : { - value1 : {type : "string"}, - value2 : {type : "string"} - } - }, - complex2 : { - type : "object", - properties : { - value1 : {type : "string"}, - value2 : {type : "string"} - } - } - } -} \ No newline at end of file diff --git a/modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/typelevels/ParseDocumentTypeLevelsTests.java b/modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/typelevels/ParseDocumentTypeLevelsTests.java new file mode 100644 index 00000000000..068b62ee049 --- /dev/null +++ b/modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/typelevels/ParseDocumentTypeLevelsTests.java @@ -0,0 +1,233 @@ +/* + * 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.typelevels; + +import org.elasticsearch.common.xcontent.XContentFactory; +import org.elasticsearch.common.xcontent.XContentType; +import org.elasticsearch.index.mapper.ParsedDocument; +import org.elasticsearch.index.mapper.xcontent.XContentDocumentMapper; +import org.elasticsearch.index.mapper.xcontent.XContentMapperTests; +import org.testng.annotations.Test; + +import static org.hamcrest.MatcherAssert.*; +import static org.hamcrest.Matchers.*; + +/** + * @author kimchy (shay.banon) + */ +public class ParseDocumentTypeLevelsTests { + + @Test public void testNoLevel() throws Exception { + String defaultMapping = XContentFactory.contentTextBuilder(XContentType.JSON).startObject().startObject("type").endObject().endObject().string(); + + XContentDocumentMapper defaultMapper = XContentMapperTests.newParser().parse(defaultMapping); + + ParsedDocument doc = defaultMapper.parse("type", "1", XContentFactory.jsonBuilder() + .startObject() + .field("test1", "value1") + .field("test2", "value2") + .startObject("inner").field("inner_field", "inner_value").endObject() + .endObject() + .copiedBytes()); + + assertThat(doc.doc().get("test1"), equalTo("value1")); + assertThat(doc.doc().get("test2"), equalTo("value2")); + assertThat(doc.doc().get("inner.inner_field"), equalTo("inner_value")); + } + + @Test public void testTypeLevel() throws Exception { + String defaultMapping = XContentFactory.contentTextBuilder(XContentType.JSON).startObject().startObject("type").endObject().endObject().string(); + + XContentDocumentMapper defaultMapper = XContentMapperTests.newParser().parse(defaultMapping); + + ParsedDocument doc = defaultMapper.parse("type", "1", XContentFactory.jsonBuilder() + .startObject().startObject("type") + .field("test1", "value1") + .field("test2", "value2") + .startObject("inner").field("inner_field", "inner_value").endObject() + .endObject().endObject() + .copiedBytes()); + + assertThat(doc.doc().get("test1"), equalTo("value1")); + assertThat(doc.doc().get("test2"), equalTo("value2")); + assertThat(doc.doc().get("inner.inner_field"), equalTo("inner_value")); + } + + @Test public void testNoLevelWithFieldTypeAsValue() throws Exception { + String defaultMapping = XContentFactory.contentTextBuilder(XContentType.JSON).startObject().startObject("type").endObject().endObject().string(); + + XContentDocumentMapper defaultMapper = XContentMapperTests.newParser().parse(defaultMapping); + + ParsedDocument doc = defaultMapper.parse("type", "1", XContentFactory.jsonBuilder() + .startObject() + .field("type", "value_type") + .field("test1", "value1") + .field("test2", "value2") + .startObject("inner").field("inner_field", "inner_value").endObject() + .endObject() + .copiedBytes()); + + assertThat(doc.doc().get("type"), equalTo("value_type")); + assertThat(doc.doc().get("test1"), equalTo("value1")); + assertThat(doc.doc().get("test2"), equalTo("value2")); + assertThat(doc.doc().get("inner.inner_field"), equalTo("inner_value")); + } + + @Test public void testTypeLevelWithFieldTypeAsValue() throws Exception { + String defaultMapping = XContentFactory.contentTextBuilder(XContentType.JSON).startObject().startObject("type").endObject().endObject().string(); + + XContentDocumentMapper defaultMapper = XContentMapperTests.newParser().parse(defaultMapping); + + ParsedDocument doc = defaultMapper.parse("type", "1", XContentFactory.jsonBuilder() + .startObject().startObject("type") + .field("type", "value_type") + .field("test1", "value1") + .field("test2", "value2") + .startObject("inner").field("inner_field", "inner_value").endObject() + .endObject().endObject() + .copiedBytes()); + + assertThat(doc.doc().get("type"), equalTo("value_type")); + assertThat(doc.doc().get("test1"), equalTo("value1")); + assertThat(doc.doc().get("test2"), equalTo("value2")); + assertThat(doc.doc().get("inner.inner_field"), equalTo("inner_value")); + } + + @Test public void testNoLevelWithFieldTypeAsObject() throws Exception { + String defaultMapping = XContentFactory.contentTextBuilder(XContentType.JSON).startObject().startObject("type").endObject().endObject().string(); + + XContentDocumentMapper defaultMapper = XContentMapperTests.newParser().parse(defaultMapping); + + ParsedDocument doc = defaultMapper.parse("type", "1", XContentFactory.jsonBuilder() + .startObject() + .startObject("type").field("type_field", "type_value").endObject() + .field("test1", "value1") + .field("test2", "value2") + .startObject("inner").field("inner_field", "inner_value").endObject() + .endObject() + .copiedBytes()); + + // in this case, we analyze the type object as the actual document, and ignore the other same level fields + assertThat(doc.doc().get("type_field"), equalTo("type_value")); + assertThat(doc.doc().get("test1"), nullValue()); + assertThat(doc.doc().get("test2"), nullValue()); + } + + @Test public void testTypeLevelWithFieldTypeAsObject() throws Exception { + String defaultMapping = XContentFactory.contentTextBuilder(XContentType.JSON).startObject().startObject("type").endObject().endObject().string(); + + XContentDocumentMapper defaultMapper = XContentMapperTests.newParser().parse(defaultMapping); + + ParsedDocument doc = defaultMapper.parse("type", "1", XContentFactory.jsonBuilder() + .startObject().startObject("type") + .startObject("type").field("type_field", "type_value").endObject() + .field("test1", "value1") + .field("test2", "value2") + .startObject("inner").field("inner_field", "inner_value").endObject() + .endObject().endObject() + .copiedBytes()); + + assertThat(doc.doc().get("type.type_field"), equalTo("type_value")); + assertThat(doc.doc().get("test1"), equalTo("value1")); + assertThat(doc.doc().get("test2"), equalTo("value2")); + assertThat(doc.doc().get("inner.inner_field"), equalTo("inner_value")); + } + + @Test public void testNoLevelWithFieldTypeAsValueNotFirst() throws Exception { + String defaultMapping = XContentFactory.contentTextBuilder(XContentType.JSON).startObject().startObject("type").endObject().endObject().string(); + + XContentDocumentMapper defaultMapper = XContentMapperTests.newParser().parse(defaultMapping); + + ParsedDocument doc = defaultMapper.parse("type", "1", XContentFactory.jsonBuilder() + .startObject().startObject("type") + .field("test1", "value1") + .field("test2", "value2") + .field("type", "value_type") + .startObject("inner").field("inner_field", "inner_value").endObject() + .endObject().endObject() + .copiedBytes()); + + assertThat(doc.doc().get("type"), equalTo("value_type")); + assertThat(doc.doc().get("test1"), equalTo("value1")); + assertThat(doc.doc().get("test2"), equalTo("value2")); + assertThat(doc.doc().get("inner.inner_field"), equalTo("inner_value")); + } + + @Test public void testTypeLevelWithFieldTypeAsValueNotFirst() throws Exception { + String defaultMapping = XContentFactory.contentTextBuilder(XContentType.JSON).startObject().startObject("type").endObject().endObject().string(); + + XContentDocumentMapper defaultMapper = XContentMapperTests.newParser().parse(defaultMapping); + + ParsedDocument doc = defaultMapper.parse("type", "1", XContentFactory.jsonBuilder() + .startObject().startObject("type") + .field("test1", "value1") + .field("type", "value_type") + .field("test2", "value2") + .startObject("inner").field("inner_field", "inner_value").endObject() + .endObject().endObject() + .copiedBytes()); + + assertThat(doc.doc().get("type"), equalTo("value_type")); + assertThat(doc.doc().get("test1"), equalTo("value1")); + assertThat(doc.doc().get("test2"), equalTo("value2")); + assertThat(doc.doc().get("inner.inner_field"), equalTo("inner_value")); + } + + @Test public void testNoLevelWithFieldTypeAsObjectNotFirst() throws Exception { + String defaultMapping = XContentFactory.contentTextBuilder(XContentType.JSON).startObject().startObject("type").endObject().endObject().string(); + + XContentDocumentMapper defaultMapper = XContentMapperTests.newParser().parse(defaultMapping); + + ParsedDocument doc = defaultMapper.parse("type", "1", XContentFactory.jsonBuilder() + .startObject() + .field("test1", "value1") + .startObject("type").field("type_field", "type_value").endObject() + .field("test2", "value2") + .startObject("inner").field("inner_field", "inner_value").endObject() + .endObject() + .copiedBytes()); + + // when the type is not the first one, we don't confuse it... + assertThat(doc.doc().get("type.type_field"), equalTo("type_value")); + assertThat(doc.doc().get("test1"), equalTo("value1")); + assertThat(doc.doc().get("test2"), equalTo("value2")); + assertThat(doc.doc().get("inner.inner_field"), equalTo("inner_value")); + } + + @Test public void testTypeLevelWithFieldTypeAsObjectNotFirst() throws Exception { + String defaultMapping = XContentFactory.contentTextBuilder(XContentType.JSON).startObject().startObject("type").endObject().endObject().string(); + + XContentDocumentMapper defaultMapper = XContentMapperTests.newParser().parse(defaultMapping); + + ParsedDocument doc = defaultMapper.parse("type", "1", XContentFactory.jsonBuilder() + .startObject().startObject("type") + .field("test1", "value1") + .startObject("type").field("type_field", "type_value").endObject() + .field("test2", "value2") + .startObject("inner").field("inner_field", "inner_value").endObject() + .endObject().endObject() + .copiedBytes()); + + assertThat(doc.doc().get("type.type_field"), equalTo("type_value")); + assertThat(doc.doc().get("test1"), equalTo("value1")); + assertThat(doc.doc().get("test2"), equalTo("value2")); + assertThat(doc.doc().get("inner.inner_field"), equalTo("inner_value")); + } +} diff --git a/modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/typelevels/ParseMappingTypeLevelTests.java b/modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/typelevels/ParseMappingTypeLevelTests.java new file mode 100644 index 00000000000..941c4208711 --- /dev/null +++ b/modules/elasticsearch/src/test/java/org/elasticsearch/index/mapper/xcontent/typelevels/ParseMappingTypeLevelTests.java @@ -0,0 +1,49 @@ +/* + * 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.typelevels; + +import org.elasticsearch.common.xcontent.XContentFactory; +import org.elasticsearch.common.xcontent.XContentType; +import org.elasticsearch.index.mapper.xcontent.XContentDocumentMapper; +import org.elasticsearch.index.mapper.xcontent.XContentMapperTests; +import org.testng.annotations.Test; + +import static org.hamcrest.MatcherAssert.*; +import static org.hamcrest.Matchers.*; + +/** + * @author kimchy (shay.banon) + */ +public class ParseMappingTypeLevelTests { + + @Test public void testTypeLevel() throws Exception { + String mapping = XContentFactory.contentTextBuilder(XContentType.JSON).startObject().startObject("type") + .startObject("_source").field("enabled", false).endObject() + .endObject().endObject().string(); + + XContentDocumentMapper mapper = XContentMapperTests.newParser().parse("type", mapping); + assertThat(mapper.type(), equalTo("type")); + assertThat(mapper.sourceMapper().enabled(), equalTo(false)); + + mapper = XContentMapperTests.newParser().parse(mapping); + assertThat(mapper.type(), equalTo("type")); + assertThat(mapper.sourceMapper().enabled(), equalTo(false)); + } +}