diff --git a/server/src/test/java/org/elasticsearch/index/mapper/CamelCaseFieldNameTests.java b/server/src/test/java/org/elasticsearch/index/mapper/CamelCaseFieldNameTests.java index 83aca847fa4..11453471b28 100644 --- a/server/src/test/java/org/elasticsearch/index/mapper/CamelCaseFieldNameTests.java +++ b/server/src/test/java/org/elasticsearch/index/mapper/CamelCaseFieldNameTests.java @@ -19,37 +19,22 @@ package org.elasticsearch.index.mapper; -import org.elasticsearch.common.Strings; -import org.elasticsearch.common.bytes.BytesReference; -import org.elasticsearch.common.xcontent.XContentFactory; -import org.elasticsearch.common.xcontent.XContentType; -import org.elasticsearch.index.IndexService; -import org.elasticsearch.test.ESSingleNodeTestCase; +public class CamelCaseFieldNameTests extends MapperServiceTestCase { -public class CamelCaseFieldNameTests extends ESSingleNodeTestCase { public void testCamelCaseFieldNameStaysAsIs() throws Exception { - String mapping = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("type") - .endObject().endObject()); + MapperService mapperService = createMapperService(mapping(b -> {})); - IndexService index = createIndex("test"); - client().admin().indices().preparePutMapping("test").setType("type").setSource(mapping, XContentType.JSON).get(); - DocumentMapper documentMapper = index.mapperService().documentMapper("type"); - - ParsedDocument doc = documentMapper.parse(new SourceToParse("test", "type", "1", - BytesReference.bytes(XContentFactory.jsonBuilder().startObject() - .field("thisIsCamelCase", "value1") - .endObject()), - XContentType.JSON)); + ParsedDocument doc = mapperService.documentMapper().parse(source(b -> b.field("thisIsCamelCase", "value1"))); assertNotNull(doc.dynamicMappingsUpdate()); - client().admin().indices().preparePutMapping("test").setType("type") - .setSource(doc.dynamicMappingsUpdate().toString(), XContentType.JSON).get(); - documentMapper = index.mapperService().documentMapper("type"); + merge(mapperService, dynamicMapping(doc.dynamicMappingsUpdate())); + + DocumentMapper documentMapper = mapperService.documentMapper(); assertNotNull(documentMapper.mappers().getMapper("thisIsCamelCase")); assertNull(documentMapper.mappers().getMapper("this_is_camel_case")); - documentMapper = index.mapperService().documentMapperParser().parse("type", documentMapper.mappingSource()); + documentMapper = mapperService.documentMapperParser().parse("_doc", documentMapper.mappingSource()); assertNotNull(documentMapper.mappers().getMapper("thisIsCamelCase")); assertNull(documentMapper.mappers().getMapper("this_is_camel_case")); diff --git a/server/src/test/java/org/elasticsearch/index/mapper/CopyToMapperTests.java b/server/src/test/java/org/elasticsearch/index/mapper/CopyToMapperTests.java index 8a7a42e18f0..3eeab79ac17 100644 --- a/server/src/test/java/org/elasticsearch/index/mapper/CopyToMapperTests.java +++ b/server/src/test/java/org/elasticsearch/index/mapper/CopyToMapperTests.java @@ -20,21 +20,15 @@ package org.elasticsearch.index.mapper; import org.apache.lucene.index.IndexableField; -import org.elasticsearch.common.Strings; import org.elasticsearch.common.bytes.BytesReference; -import org.elasticsearch.common.compress.CompressedXContent; import org.elasticsearch.common.xcontent.ToXContent; import org.elasticsearch.common.xcontent.XContentBuilder; -import org.elasticsearch.common.xcontent.XContentFactory; import org.elasticsearch.common.xcontent.XContentParser; -import org.elasticsearch.common.xcontent.XContentType; import org.elasticsearch.common.xcontent.json.JsonXContent; -import org.elasticsearch.index.IndexService; -import org.elasticsearch.index.mapper.MapperService.MergeReason; import org.elasticsearch.index.mapper.ParseContext.Document; -import org.elasticsearch.test.ESSingleNodeTestCase; import org.hamcrest.Matchers; +import java.io.IOException; import java.util.Arrays; import java.util.List; import java.util.Map; @@ -44,35 +38,33 @@ import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.startsWith; -public class CopyToMapperTests extends ESSingleNodeTestCase { +public class CopyToMapperTests extends MapperServiceTestCase { + @SuppressWarnings("unchecked") public void testCopyToFieldsParsing() throws Exception { - String mapping = Strings.toString(jsonBuilder().startObject().startObject("type1").startObject("properties") - .startObject("copy_test") - .field("type", "text") - .array("copy_to", "another_field", "cyclic_test") - .endObject() - - .startObject("another_field") - .field("type", "text") - .endObject() - - .startObject("cyclic_test") - .field("type", "text") - .array("copy_to", "copy_test") - .endObject() - - .startObject("int_to_str_test") - .field("type", "integer") - .field("doc_values", false) - .array("copy_to", "another_field", "new_field") - .endObject() - .endObject().endObject().endObject()); - - IndexService index = createIndex("test"); - client().admin().indices().preparePutMapping("test").setType("type1").setSource(mapping, XContentType.JSON).get(); - DocumentMapper docMapper = index.mapperService().documentMapper("type1"); - Mapper fieldMapper = docMapper.mappers().getMapper("copy_test"); + MapperService mapperService = createMapperService(mapping(b -> { + b.startObject("copy_test"); + { + b.field("type", "text"); + b.array("copy_to", "another_field", "cyclic_test"); + } + b.endObject(); + b.startObject("another_field").field("type", "text").endObject(); + b.startObject("cyclic_test"); + { + b.field("type", "text"); + b.array("copy_to", "copy_test"); + } + b.endObject(); + b.startObject("int_to_str_test"); + { + b.field("type", "integer"); + b.field("doc_values", false); + b.array("copy_to", "another_field", "new_field"); + } + b.endObject(); + })); + Mapper fieldMapper = mapperService.documentMapper().mappers().getMapper("copy_test"); // Check json serialization TextFieldMapper stringFieldMapper = (TextFieldMapper) fieldMapper; @@ -91,13 +83,11 @@ public class CopyToMapperTests extends ESSingleNodeTestCase { assertThat(copyToList.get(1), equalTo("cyclic_test")); // Check data parsing - BytesReference json = BytesReference.bytes(jsonBuilder().startObject() - .field("copy_test", "foo") - .field("cyclic_test", "bar") - .field("int_to_str_test", 42) - .endObject()); - - ParsedDocument parsedDoc = docMapper.parse(new SourceToParse("test", "type1", "1", json, XContentType.JSON)); + ParsedDocument parsedDoc = mapperService.documentMapper().parse(source(b -> { + b.field("copy_test", "foo"); + b.field("cyclic_test", "bar"); + b.field("int_to_str_test", 42); + })); ParseContext.Document doc = parsedDoc.rootDoc(); assertThat(doc.getFields("copy_test").length, equalTo(2)); assertThat(doc.getFields("copy_test")[0].stringValue(), equalTo("foo")); @@ -118,43 +108,41 @@ public class CopyToMapperTests extends ESSingleNodeTestCase { assertThat(doc.getFields("new_field")[0].numericValue().intValue(), equalTo(42)); assertNotNull(parsedDoc.dynamicMappingsUpdate()); - client().admin().indices().preparePutMapping("test").setType("type1") - .setSource(parsedDoc.dynamicMappingsUpdate().toString(), XContentType.JSON).get(); + merge(mapperService, dynamicMapping(parsedDoc.dynamicMappingsUpdate())); - docMapper = index.mapperService().documentMapper("type1"); - fieldMapper = docMapper.mappers().getMapper("new_field"); + fieldMapper = mapperService.documentMapper().mappers().getMapper("new_field"); assertThat(fieldMapper.typeName(), equalTo("long")); } public void testCopyToFieldsInnerObjectParsing() throws Exception { - String mapping = Strings.toString(jsonBuilder().startObject().startObject("type1").startObject("properties") + DocumentMapper docMapper = createDocumentMapper(mapping(b -> { + b.startObject("copy_test"); + { + b.field("type", "text"); + b.field("copy_to", "very.inner.field"); + } + b.endObject(); + b.startObject("very"); + { + b.field("type", "object"); + b.startObject("properties"); + { + b.startObject("inner").field("type", "object").endObject(); + } + b.endObject(); + } + b.endObject(); + })); - .startObject("copy_test") - .field("type", "text") - .field("copy_to", "very.inner.field") - .endObject() + ParseContext.Document doc = docMapper.parse(source(b -> { + b.field("copy_test", "foo"); + b.startObject("foo"); + { + b.startObject("bar").field("baz", "zoo").endObject(); + } + b.endObject(); + })).rootDoc(); - .startObject("very") - .field("type", "object") - .startObject("properties") - .startObject("inner") - .field("type", "object") - .endObject() - .endObject() - .endObject() - - .endObject().endObject().endObject()); - - DocumentMapper docMapper = createIndex("test").mapperService().documentMapperParser() - .parse("type1", new CompressedXContent(mapping)); - - BytesReference json = BytesReference.bytes(jsonBuilder().startObject() - .field("copy_test", "foo") - .startObject("foo").startObject("bar").field("baz", "zoo").endObject().endObject() - .endObject()); - - ParseContext.Document doc = docMapper.parse(new SourceToParse("test", "type1", "1", json, - XContentType.JSON)).rootDoc(); assertThat(doc.getFields("copy_test").length, equalTo(1)); assertThat(doc.getFields("copy_test")[0].stringValue(), equalTo("foo")); @@ -164,25 +152,20 @@ public class CopyToMapperTests extends ESSingleNodeTestCase { } public void testCopyToDynamicInnerObjectParsing() throws Exception { - String mapping = Strings.toString(jsonBuilder().startObject().startObject("type1") - .startObject("properties") - .startObject("copy_test") - .field("type", "text") - .field("copy_to", "very.inner.field") - .endObject() - .endObject() - .endObject().endObject()); + DocumentMapper docMapper = createDocumentMapper(mapping(b -> { + b.startObject("copy_test"); + { + b.field("type", "text"); + b.field("copy_to", "very.inner.field"); + } + b.endObject(); + })); - DocumentMapper docMapper = createIndex("test").mapperService().documentMapperParser() - .parse("type1", new CompressedXContent(mapping)); + ParseContext.Document doc = docMapper.parse(source(b -> { + b.field("copy_test", "foo"); + b.field("new_field", "bar"); + })).rootDoc(); - BytesReference json = BytesReference.bytes(jsonBuilder().startObject() - .field("copy_test", "foo") - .field("new_field", "bar") - .endObject()); - - ParseContext.Document doc = docMapper.parse(new SourceToParse("test", "type1", "1", json, - XContentType.JSON)).rootDoc(); assertThat(doc.getFields("copy_test").length, equalTo(1)); assertThat(doc.getFields("copy_test")[0].stringValue(), equalTo("foo")); @@ -194,33 +177,30 @@ public class CopyToMapperTests extends ESSingleNodeTestCase { } public void testCopyToDynamicInnerInnerObjectParsing() throws Exception { - String mapping = Strings.toString(jsonBuilder().startObject().startObject("type1") - .startObject("properties") - .startObject("copy_test") - .field("type", "text") - .field("copy_to", "very.far.inner.field") - .endObject() - .startObject("very") - .field("type", "object") - .startObject("properties") - .startObject("far") - .field("type", "object") - .endObject() - .endObject() - .endObject() - .endObject() - .endObject().endObject()); + DocumentMapper docMapper = createDocumentMapper(mapping(b -> { + b.startObject("copy_test"); + { + b.field("type", "text"); + b.field("copy_to", "very.far.inner.field"); + } + b.endObject(); + b.startObject("very"); + { + b.field("type", "object"); + b.startObject("properties"); + { + b.startObject("far").field("type", "object").endObject(); + } + b.endObject(); + } + b.endObject(); + })); - DocumentMapper docMapper = createIndex("test").mapperService().documentMapperParser() - .parse("type1", new CompressedXContent(mapping)); + ParseContext.Document doc = docMapper.parse(source(b -> { + b.field("copy_test", "foo"); + b.field("new_field", "bar"); + })).rootDoc(); - BytesReference json = BytesReference.bytes(jsonBuilder().startObject() - .field("copy_test", "foo") - .field("new_field", "bar") - .endObject()); - - ParseContext.Document doc = docMapper.parse(new SourceToParse("test", "type1", "1", json, - XContentType.JSON)).rootDoc(); assertThat(doc.getFields("copy_test").length, equalTo(1)); assertThat(doc.getFields("copy_test")[0].stringValue(), equalTo("foo")); @@ -232,95 +212,84 @@ public class CopyToMapperTests extends ESSingleNodeTestCase { } public void testCopyToStrictDynamicInnerObjectParsing() throws Exception { - String mapping = Strings.toString(jsonBuilder().startObject().startObject("type1") - .field("dynamic", "strict") - .startObject("properties") - .startObject("copy_test") - .field("type", "text") - .field("copy_to", "very.inner.field") - .endObject() - .endObject() - .endObject().endObject()); + DocumentMapper docMapper = createDocumentMapper(topMapping(b -> { + b.field("dynamic", "strict"); + b.startObject("properties"); + { + b.startObject("copy_test"); + { + b.field("type", "text"); + b.field("copy_to", "very.inner.field"); + } + b.endObject(); + } + b.endObject(); + })); - DocumentMapper docMapper = createIndex("test").mapperService().documentMapperParser() - .parse("type1", new CompressedXContent(mapping)); + MapperParsingException e = expectThrows(MapperParsingException.class, + () -> docMapper.parse(source(b -> b.field("copy_test", "foo")))); - BytesReference json = BytesReference.bytes(jsonBuilder().startObject() - .field("copy_test", "foo") - .endObject()); - - try { - docMapper.parse(new SourceToParse("test", "type1", "1", json, XContentType.JSON)).rootDoc(); - fail(); - } catch (MapperParsingException ex) { - assertThat(ex.getMessage(), startsWith("mapping set to strict, dynamic introduction of [very] within [type1] is not allowed")); - } + assertThat(e.getMessage(), startsWith("mapping set to strict, dynamic introduction of [very] within [_doc] is not allowed")); } public void testCopyToInnerStrictDynamicInnerObjectParsing() throws Exception { - String mapping = Strings.toString(jsonBuilder().startObject().startObject("type1") - .startObject("properties") - .startObject("copy_test") - .field("type", "text") - .field("copy_to", "very.far.field") - .endObject() - .startObject("very") - .field("type", "object") - .startObject("properties") - .startObject("far") - .field("type", "object") - .field("dynamic", "strict") - .endObject() - .endObject() - .endObject() - .endObject() - .endObject().endObject()); + DocumentMapper docMapper = createDocumentMapper(mapping(b -> { + b.startObject("copy_test"); + { + b.field("type", "text"); + b.field("copy_to", "very.far.field"); + } + b.endObject(); + b.startObject("very"); + { + b.field("type", "object"); + b.startObject("properties"); + { + b.startObject("far"); + { + b.field("type", "object"); + b.field("dynamic", "strict"); + } + b.endObject(); + } + b.endObject(); + } + b.endObject(); + })); - DocumentMapper docMapper = createIndex("test").mapperService().documentMapperParser() - .parse("type1", new CompressedXContent(mapping)); + MapperParsingException e = expectThrows(MapperParsingException.class, + () -> docMapper.parse(source(b -> b.field("copy_test", "foo")))); - BytesReference json = BytesReference.bytes(jsonBuilder().startObject() - .field("copy_test", "foo") - .endObject()); - - try { - docMapper.parse(new SourceToParse("test", "type1", "1", json, XContentType.JSON)).rootDoc(); - fail(); - } catch (MapperParsingException ex) { - assertThat(ex.getMessage(), - startsWith("mapping set to strict, dynamic introduction of [field] within [very.far] is not allowed")); - } + assertThat(e.getMessage(), + startsWith("mapping set to strict, dynamic introduction of [field] within [very.far] is not allowed")); } public void testCopyToFieldMerge() throws Exception { - String mappingBefore = Strings.toString(jsonBuilder().startObject().startObject("type1").startObject("properties") - .startObject("copy_test") - .field("type", "text") - .array("copy_to", "foo", "bar") - .endObject() - - .endObject().endObject().endObject()); - - String mappingAfter = Strings.toString(jsonBuilder().startObject().startObject("type1").startObject("properties") - - .startObject("copy_test") - .field("type", "text") - .array("copy_to", "baz", "bar") - .endObject() - - .endObject().endObject().endObject()); - - MapperService mapperService = createIndex("test").mapperService(); - DocumentMapper docMapperBefore = mapperService.merge("type1", new CompressedXContent(mappingBefore), - MapperService.MergeReason.MAPPING_UPDATE); + MapperService mapperService = createMapperService(mapping(b -> { + b.startObject("copy_test"); + { + b.field("type", "text"); + b.array("copy_to", "foo", "bar"); + } + b.endObject(); + })); + DocumentMapper docMapperBefore = mapperService.documentMapper(); FieldMapper fieldMapperBefore = (FieldMapper) docMapperBefore.mappers().getMapper("copy_test"); assertEquals(Arrays.asList("foo", "bar"), fieldMapperBefore.copyTo().copyToFields()); - DocumentMapper docMapperAfter = mapperService.merge("type1", new CompressedXContent(mappingAfter), - MapperService.MergeReason.MAPPING_UPDATE); + merge(mapperService, mapping(b -> { + b.startObject("copy_test"); + { + b.field("type", "text"); + b.array("copy_to", "baz", "bar"); + } + b.endObject(); + })); + + DocumentMapper docMapperAfter = mapperService.documentMapper(); FieldMapper fieldMapperAfter = (FieldMapper) docMapperAfter.mappers().getMapper("copy_test"); assertEquals(Arrays.asList("baz", "bar"), fieldMapperAfter.copyTo().copyToFields()); @@ -328,73 +297,84 @@ public class CopyToMapperTests extends ESSingleNodeTestCase { } public void testCopyToNestedField() throws Exception { - IndexService indexService = createIndex("test"); - DocumentMapperParser parser = indexService.mapperService().documentMapperParser(); - XContentBuilder mapping = jsonBuilder().startObject() - .startObject("type") - .startObject("properties") - .startObject("target") - .field("type", "long") - .field("doc_values", false) - .endObject() - .startObject("n1") - .field("type", "nested") - .startObject("properties") - .startObject("target") - .field("type", "long") - .field("doc_values", false) - .endObject() - .startObject("n2") - .field("type", "nested") - .startObject("properties") - .startObject("target") - .field("type", "long") - .field("doc_values", false) - .endObject() - .startObject("source") - .field("type", "long") - .field("doc_values", false) - .startArray("copy_to") - .value("target") // should go to the root doc - .value("n1.target") // should go to the parent doc - .value("n1.n2.target") // should go to the current doc - .endArray() - .endObject() - .endObject() - .endObject() - .endObject() - .endObject() - .endObject() - .endObject() - .endObject(); + DocumentMapper mapper = createDocumentMapper(mapping(b -> { + b.startObject("target"); + { + b.field("type", "long"); + b.field("doc_values", false); + } + b.endObject(); + b.startObject("n1"); + { + b.field("type", "nested"); + b.startObject("properties"); + { + b.startObject("target"); + { + b.field("type", "long"); + b.field("doc_values", false); + } + b.endObject(); + b.startObject("n2"); + { + b.field("type", "nested"); + b.startObject("properties"); + { + b.startObject("target"); + { + b.field("type", "long"); + b.field("doc_values", false); + } + b.endObject(); + b.startObject("source"); + { + b.field("type", "long"); + b.field("doc_values", false); + b.startArray("copy_to"); + { + b.value("target"); // should go to the root doc + b.value("n1.target"); // should go to the parent doc + b.value("n1.n2.target"); // should go to the current doc + } + b.endArray(); + } + b.endObject(); + } + b.endObject(); + } + b.endObject(); + } + b.endObject(); + } + b.endObject(); + })); - DocumentMapper mapper = parser.parse("type", new CompressedXContent(Strings.toString(mapping))); + ParsedDocument doc = mapper.parse(source(b -> { + b.startArray("n1"); + { + b.startObject(); + { + b.startArray("n2"); + { + b.startObject().field("source", 3).endObject(); + b.startObject().field("source", 5).endObject(); + } + b.endArray(); + } + b.endObject(); + b.startObject(); + { + b.startArray("n2"); + { + b.startObject().field("source", 7).endObject(); + } + b.endArray(); + } + b.endObject(); + } + b.endArray(); + })); - XContentBuilder jsonDoc = XContentFactory.jsonBuilder() - .startObject() - .startArray("n1") - .startObject() - .startArray("n2") - .startObject() - .field("source", 3) - .endObject() - .startObject() - .field("source", 5) - .endObject() - .endArray() - .endObject() - .startObject() - .startArray("n2") - .startObject() - .field("source", 7) - .endObject() - .endArray() - .endObject() - .endArray() - .endObject(); - - ParsedDocument doc = mapper.parse(new SourceToParse("test", "type", "1", - BytesReference.bytes(jsonDoc), XContentType.JSON)); assertEquals(6, doc.docs().size()); Document nested = doc.docs().get(0); @@ -428,145 +408,139 @@ public class CopyToMapperTests extends ESSingleNodeTestCase { assertFieldValue(root, "n1.n2.target"); } - public void testCopyToChildNested() throws Exception { - IndexService indexService = createIndex("test"); - XContentBuilder rootToNestedMapping = jsonBuilder().startObject() - .startObject("_doc") - .startObject("properties") - .startObject("source") - .field("type", "long") - .field("copy_to", "n1.target") - .endObject() - .startObject("n1") - .field("type", "nested") - .startObject("properties") - .startObject("target") - .field("type", "long") - .endObject() - .endObject() - .endObject() - .endObject() - .endObject() - .endObject(); - IllegalArgumentException e = expectThrows(IllegalArgumentException.class, - () -> indexService.mapperService().merge("_doc", new CompressedXContent(BytesReference.bytes(rootToNestedMapping)), - MergeReason.MAPPING_UPDATE)); + public void testCopyToChildNested() { + + IllegalArgumentException e = expectThrows(IllegalArgumentException.class, () -> createDocumentMapper(mapping(b -> { + b.startObject("source"); + { + b.field("type", "long"); + b.field("copy_to", "n1.target"); + } + b.endObject(); + b.startObject("n1"); + { + b.field("type", "nested"); + b.startObject("properties"); + { + b.startObject("target").field("type", "long").endObject(); + } + b.endObject(); + } + b.endObject(); + }))); assertThat(e.getMessage(), Matchers.startsWith("Illegal combination of [copy_to] and [nested] mappings")); - XContentBuilder nestedToNestedMapping = jsonBuilder().startObject() - .startObject("_doc") - .startObject("properties") - .startObject("n1") - .field("type", "nested") - .startObject("properties") - .startObject("source") - .field("type", "long") - .field("copy_to", "n1.n2.target") - .endObject() - .startObject("n2") - .field("type", "nested") - .startObject("properties") - .startObject("target") - .field("type", "long") - .endObject() - .endObject() - .endObject() - .endObject() - .endObject() - .endObject() - .endObject() - .endObject(); - e = expectThrows(IllegalArgumentException.class, - () -> indexService.mapperService().merge("_doc", new CompressedXContent(BytesReference.bytes(nestedToNestedMapping)), - MergeReason.MAPPING_UPDATE)); + expectThrows(IllegalArgumentException.class, () -> createDocumentMapper(mapping(b -> { + b.startObject("n1"); + { + b.field("type", "nested"); + b.startObject("properties"); + { + b.startObject("source"); + { + b.field("type", "long"); + b.field("copy_to", "n1.n2.target"); + } + b.endObject(); + b.startObject("n2"); + { + b.field("type", "nested"); + b.startObject("properties"); + { + b.startObject("target").field("type", "long").endObject(); + } + b.endObject(); + } + b.endObject(); + } + b.endObject(); + } + b.endObject(); + }))); } - public void testCopyToSiblingNested() throws Exception { - IndexService indexService = createIndex("test"); - XContentBuilder rootToNestedMapping = jsonBuilder().startObject() - .startObject("_doc") - .startObject("properties") - .startObject("n1") - .field("type", "nested") - .startObject("properties") - .startObject("source") - .field("type", "long") - .field("copy_to", "n2.target") - .endObject() - .endObject() - .endObject() - .startObject("n2") - .field("type", "nested") - .startObject("properties") - .startObject("target") - .field("type", "long") - .endObject() - .endObject() - .endObject() - .endObject() - .endObject() - .endObject(); - IllegalArgumentException e = expectThrows(IllegalArgumentException.class, - () -> indexService.mapperService().merge("_doc", new CompressedXContent(BytesReference.bytes(rootToNestedMapping)), - MergeReason.MAPPING_UPDATE)); + public void testCopyToSiblingNested() { + IllegalArgumentException e = expectThrows(IllegalArgumentException.class, () -> createDocumentMapper(mapping(b -> { + b.startObject("n1"); + { + b.field("type", "nested"); + b.startObject("properties"); + { + b.startObject("source"); + { + b.field("type", "long"); + b.field("copy_to", "n2.target"); + } + b.endObject(); + } + b.endObject(); + } + b.endObject(); + b.startObject("n2"); + { + b.field("type", "nested"); + b.startObject("properties"); + { + b.startObject("target").field("type", "long").endObject(); + } + b.endObject(); + } + b.endObject(); + }))); assertThat(e.getMessage(), Matchers.startsWith("Illegal combination of [copy_to] and [nested] mappings")); } - public void testCopyToObject() throws Exception { - IndexService indexService = createIndex("test"); - XContentBuilder rootToNestedMapping = jsonBuilder().startObject() - .startObject("_doc") - .startObject("properties") - .startObject("source") - .field("type", "long") - .field("copy_to", "target") - .endObject() - .startObject("target") - .field("type", "object") - .endObject() - .endObject() - .endObject() - .endObject(); - IllegalArgumentException e = expectThrows(IllegalArgumentException.class, - () -> indexService.mapperService().merge("_doc", new CompressedXContent(BytesReference.bytes(rootToNestedMapping)), - MergeReason.MAPPING_UPDATE)); + public void testCopyToObject() { + IllegalArgumentException e = expectThrows(IllegalArgumentException.class, () -> createDocumentMapper(mapping(b -> { + b.startObject("source"); + { + b.field("type", "long"); + b.field("copy_to", "target"); + } + b.endObject(); + b.startObject("target"); + { + b.field("type", "object"); + } + b.endObject(); + }))); assertThat(e.getMessage(), Matchers.startsWith("Cannot copy to field [target] since it is mapped as an object")); } public void testCopyToDynamicNestedObjectParsing() throws Exception { - String mapping = Strings.toString(jsonBuilder().startObject().startObject("type1") - .startArray("dynamic_templates") - .startObject() - .startObject("objects") - .field("match_mapping_type", "object") - .startObject("mapping") - .field("type", "nested") - .endObject() - .endObject() - .endObject() - .endArray() - .startObject("properties") - .startObject("copy_test") - .field("type", "text") - .field("copy_to", "very.inner.field") - .endObject() - .endObject() - .endObject().endObject()); + DocumentMapper docMapper = createDocumentMapper(topMapping(b -> { + b.startArray("dynamic_templates"); + { + b.startObject(); + { + b.startObject("objects"); + { + b.field("match_mapping_type", "object"); + b.startObject("mapping").field("type", "nested").endObject(); + } + b.endObject(); + } + b.endObject(); + } + b.endArray(); + b.startObject("properties"); + { + b.startObject("copy_test"); + { + b.field("type", "text"); + b.field("copy_to", "very.inner.field"); + } + b.endObject(); + } + b.endObject(); + })); - DocumentMapper docMapper = createIndex("test").mapperService().documentMapperParser() - .parse("type1", new CompressedXContent(mapping)); + MapperParsingException e = expectThrows(MapperParsingException.class, () -> docMapper.parse(source(b -> { + b.field("copy_test", "foo"); + b.field("new_field", "bar"); + }))); - BytesReference json = BytesReference.bytes(jsonBuilder().startObject() - .field("copy_test", "foo") - .field("new_field", "bar") - .endObject()); - - try { - docMapper.parse(new SourceToParse("test", "type1", "1", json, XContentType.JSON)).rootDoc(); - fail(); - } catch (MapperParsingException ex) { - assertThat(ex.getMessage(), startsWith("It is forbidden to create dynamic nested objects ([very]) through `copy_to`")); - } + assertThat(e.getMessage(), startsWith("It is forbidden to create dynamic nested objects ([very]) through `copy_to`")); } private void assertFieldValue(Document doc, String field, Number... expected) { @@ -581,95 +555,78 @@ public class CopyToMapperTests extends ESSingleNodeTestCase { assertArrayEquals(expected, actual); } - public void testCopyToMultiField() throws Exception { - String mapping = Strings.toString(jsonBuilder().startObject().startObject("_doc") - .startObject("properties") - .startObject("my_field") - .field("type", "keyword") - .field("copy_to", "my_field.bar") - .startObject("fields") - .startObject("bar") - .field("type", "text") - .endObject() - .endObject() - .endObject() - .endObject() - .endObject().endObject()); - - MapperService mapperService = createIndex("test").mapperService(); - IllegalArgumentException e = expectThrows(IllegalArgumentException.class, - () -> mapperService.merge("_doc", new CompressedXContent(mapping), MergeReason.MAPPING_UPDATE)); + public void testCopyToMultiField() { + IllegalArgumentException e = expectThrows(IllegalArgumentException.class, () -> createDocumentMapper(mapping(b -> { + b.startObject("my_field"); + { + b.field("type", "keyword"); + b.field("copy_to", "my_field.bar"); + b.startObject("fields"); + { + b.startObject("bar").field("type", "text").endObject(); + } + b.endObject(); + } + b.endObject(); + }))); assertEquals("[copy_to] may not be used to copy to a multi-field: [my_field.bar]", e.getMessage()); } - public void testNestedCopyTo() throws Exception { - String mapping = Strings.toString(jsonBuilder().startObject().startObject("_doc") - .startObject("properties") - .startObject("n") - .field("type", "nested") - .startObject("properties") - .startObject("foo") - .field("type", "keyword") - .field("copy_to", "n.bar") - .endObject() - .startObject("bar") - .field("type", "text") - .endObject() - .endObject() - .endObject() - .endObject() - .endObject().endObject()); - - MapperService mapperService = createIndex("test").mapperService(); - mapperService.merge("_doc", new CompressedXContent(mapping), MergeReason.MAPPING_UPDATE); // no exception + public void testNestedCopyTo() throws IOException { + createDocumentMapper(fieldMapping(b -> { + b.field("type", "nested"); + b.startObject("properties"); + { + b.startObject("foo"); + { + b.field("type", "keyword"); + b.field("copy_to", "n.bar"); + } + b.endObject(); + b.startObject("bar").field("type", "text").endObject(); + } + b.endObject(); + })); } - public void testNestedCopyToMultiField() throws Exception { - String mapping = Strings.toString(jsonBuilder().startObject().startObject("_doc") - .startObject("properties") - .startObject("n") - .field("type", "nested") - .startObject("properties") - .startObject("my_field") - .field("type", "keyword") - .field("copy_to", "n.my_field.bar") - .startObject("fields") - .startObject("bar") - .field("type", "text") - .endObject() - .endObject() - .endObject() - .endObject() - .endObject() - .endObject() - .endObject().endObject()); - - MapperService mapperService = createIndex("test").mapperService(); - IllegalArgumentException e = expectThrows(IllegalArgumentException.class, - () -> mapperService.merge("_doc", new CompressedXContent(mapping), MergeReason.MAPPING_UPDATE)); - assertEquals("[copy_to] may not be used to copy to a multi-field: [n.my_field.bar]", e.getMessage()); + public void testNestedCopyToMultiField() { + IllegalArgumentException e = expectThrows(IllegalArgumentException.class, () -> createMapperService(fieldMapping(b -> { + b.field("type", "nested"); + b.startObject("properties"); + { + b.startObject("my_field"); + { + b.field("type", "keyword"); + b.field("copy_to", "field.my_field.bar"); + b.startObject("fields"); + { + b.startObject("bar").field("type", "text").endObject(); + } + b.endObject(); + } + b.endObject(); + } + b.endObject(); + }))); + assertEquals("[copy_to] may not be used to copy to a multi-field: [field.my_field.bar]", e.getMessage()); } - public void testCopyFromMultiField() throws Exception { - String mapping = Strings.toString(jsonBuilder().startObject().startObject("_doc") - .startObject("properties") - .startObject("my_field") - .field("type", "keyword") - .startObject("fields") - .startObject("bar") - .field("type", "text") - .field("copy_to", "my_field.baz") - .endObject() - .endObject() - .endObject() - .endObject() - .endObject().endObject()); - - MapperService mapperService = createIndex("test").mapperService(); - MapperParsingException e = expectThrows(MapperParsingException.class, - () -> mapperService.merge("_doc", new CompressedXContent(mapping), MergeReason.MAPPING_UPDATE)); + public void testCopyFromMultiField() { + MapperParsingException e = expectThrows(MapperParsingException.class, () -> createDocumentMapper(fieldMapping(b -> { + b.field("type", "keyword"); + b.startObject("fields"); + { + b.startObject("bar"); + { + b.field("type", "text"); + b.field("copy_to", "my_field.baz"); + } + b.endObject(); + } + b.endObject(); + }))); assertThat(e.getMessage(), - Matchers.containsString("copy_to in multi fields is not allowed. Found the copy_to in field [bar] " + - "which is within a multi field.")); + Matchers.containsString("copy_to in multi fields is not allowed. Found the copy_to in field [bar] " + + "which is within a multi field.")); } } diff --git a/server/src/test/java/org/elasticsearch/index/mapper/DocumentMapperParserTests.java b/server/src/test/java/org/elasticsearch/index/mapper/DocumentMapperParserTests.java index 9075c0e7a41..5ea68bbbd09 100644 --- a/server/src/test/java/org/elasticsearch/index/mapper/DocumentMapperParserTests.java +++ b/server/src/test/java/org/elasticsearch/index/mapper/DocumentMapperParserTests.java @@ -19,84 +19,63 @@ package org.elasticsearch.index.mapper; -import org.elasticsearch.common.Strings; -import org.elasticsearch.common.compress.CompressedXContent; -import org.elasticsearch.common.xcontent.XContentFactory; -import org.elasticsearch.index.IndexService; -import org.elasticsearch.test.ESSingleNodeTestCase; - -import static org.hamcrest.Matchers.equalTo; - -public class DocumentMapperParserTests extends ESSingleNodeTestCase { - public void testTypeLevel() throws Exception { - String mapping = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("type") - .endObject().endObject()); - - DocumentMapperParser parser = createIndex("test").mapperService().documentMapperParser(); - DocumentMapper mapper = parser.parse("type", new CompressedXContent(mapping)); - assertThat(mapper.type(), equalTo("type")); - } +public class DocumentMapperParserTests extends MapperServiceTestCase { public void testFieldNameWithDots() throws Exception { - IndexService indexService = createIndex("test"); - DocumentMapperParser mapperParser = indexService.mapperService().documentMapperParser(); - String mapping = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("type").startObject("properties") - .startObject("foo.bar").field("type", "text").endObject() - .startObject("foo.baz").field("type", "keyword").endObject() - .endObject().endObject().endObject()); - DocumentMapper docMapper = mapperParser.parse("type", new CompressedXContent(mapping)); + DocumentMapper docMapper = createDocumentMapper(mapping(b -> { + b.startObject("foo.bar").field("type", "text").endObject(); + b.startObject("foo.baz").field("type", "keyword").endObject(); + })); assertNotNull(docMapper.mappers().getMapper("foo.bar")); assertNotNull(docMapper.mappers().getMapper("foo.baz")); assertNotNull(docMapper.objectMappers().get("foo")); } public void testFieldNameWithDeepDots() throws Exception { - IndexService indexService = createIndex("test"); - DocumentMapperParser mapperParser = indexService.mapperService().documentMapperParser(); - String mapping = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("type").startObject("properties") - .startObject("foo.bar").field("type", "text").endObject() - .startObject("foo.baz").startObject("properties") - .startObject("deep.field").field("type", "keyword").endObject().endObject() - .endObject().endObject().endObject().endObject()); - DocumentMapper docMapper = mapperParser.parse("type", new CompressedXContent(mapping)); + DocumentMapper docMapper = createDocumentMapper(mapping(b -> { + b.startObject("foo.bar").field("type", "text").endObject(); + b.startObject("foo.baz"); + { + b.startObject("properties"); + { + b.startObject("deep.field").field("type", "keyword").endObject(); + } + b.endObject(); + } + b.endObject(); + })); assertNotNull(docMapper.mappers().getMapper("foo.bar")); assertNotNull(docMapper.mappers().getMapper("foo.baz.deep.field")); assertNotNull(docMapper.objectMappers().get("foo")); } - public void testFieldNameWithDotsConflict() throws Exception { - IndexService indexService = createIndex("test"); - DocumentMapperParser mapperParser = indexService.mapperService().documentMapperParser(); - String mapping = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("type").startObject("properties") - .startObject("foo").field("type", "text").endObject() - .startObject("foo.baz").field("type", "keyword").endObject() - .endObject().endObject().endObject()); - IllegalArgumentException e = expectThrows(IllegalArgumentException.class, () -> - mapperParser.parse("type", new CompressedXContent(mapping))); + public void testFieldNameWithDotsConflict() { + MapperParsingException e = expectThrows(MapperParsingException.class, () -> createDocumentMapper(mapping(b -> { + b.startObject("foo").field("type", "text").endObject(); + b.startObject("foo.baz").field("type", "keyword").endObject(); + }))); assertTrue(e.getMessage(), e.getMessage().contains("mapper [foo] cannot be changed from type [text] to [ObjectMapper]")); } - public void testMultiFieldsWithFieldAlias() throws Exception { - IndexService indexService = createIndex("test"); - DocumentMapperParser mapperParser = indexService.mapperService().documentMapperParser(); - String mapping = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("type") - .startObject("properties") - .startObject("field") - .field("type", "text") - .startObject("fields") - .startObject("alias") - .field("type", "alias") - .field("path", "other-field") - .endObject() - .endObject() - .endObject() - .startObject("other-field") - .field("type", "keyword") - .endObject() - .endObject() - .endObject().endObject()); - MapperParsingException e = expectThrows(MapperParsingException.class, () -> - mapperParser.parse("type", new CompressedXContent(mapping))); - assertEquals("Type [alias] cannot be used in multi field", e.getMessage()); + public void testMultiFieldsWithFieldAlias() { + MapperParsingException e = expectThrows(MapperParsingException.class, () -> createDocumentMapper(mapping(b -> { + b.startObject("field"); + { + b.field("type", "text"); + b.startObject("fields"); + { + b.startObject("alias"); + { + b.field("type", "alias"); + b.field("path", "other-field"); + } + b.endObject(); + } + b.endObject(); + } + b.endObject(); + b.startObject("other-field").field("type", "keyword").endObject(); + }))); + assertEquals("Failed to parse mapping [_doc]: Type [alias] cannot be used in multi field", e.getMessage()); } } diff --git a/server/src/test/java/org/elasticsearch/index/mapper/DocumentMapperTests.java b/server/src/test/java/org/elasticsearch/index/mapper/DocumentMapperTests.java index 56bcd656cd9..a8301ac250f 100644 --- a/server/src/test/java/org/elasticsearch/index/mapper/DocumentMapperTests.java +++ b/server/src/test/java/org/elasticsearch/index/mapper/DocumentMapperTests.java @@ -19,18 +19,19 @@ package org.elasticsearch.index.mapper; -import org.elasticsearch.common.Strings; -import org.elasticsearch.common.bytes.BytesArray; -import org.elasticsearch.common.bytes.BytesReference; +import org.apache.lucene.analysis.core.KeywordAnalyzer; +import org.apache.lucene.analysis.core.WhitespaceAnalyzer; +import org.apache.lucene.analysis.standard.StandardAnalyzer; import org.elasticsearch.common.compress.CompressedXContent; -import org.elasticsearch.common.settings.Settings; -import org.elasticsearch.common.xcontent.XContentBuilder; -import org.elasticsearch.common.xcontent.XContentFactory; -import org.elasticsearch.common.xcontent.XContentType; +import org.elasticsearch.index.IndexSettings; +import org.elasticsearch.index.analysis.AnalyzerScope; +import org.elasticsearch.index.analysis.IndexAnalyzers; +import org.elasticsearch.index.analysis.NamedAnalyzer; import org.elasticsearch.index.mapper.MapperService.MergeReason; -import org.elasticsearch.test.ESSingleNodeTestCase; import java.io.IOException; +import java.util.Collections; +import java.util.HashMap; import java.util.Map; import java.util.concurrent.CyclicBarrier; import java.util.concurrent.atomic.AtomicBoolean; @@ -41,24 +42,29 @@ import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.notNullValue; import static org.hamcrest.Matchers.nullValue; -public class DocumentMapperTests extends ESSingleNodeTestCase { +public class DocumentMapperTests extends MapperServiceTestCase { public void testAddFields() throws Exception { - String stage1Mapping = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("person").startObject("properties") - .startObject("name").field("type", "text").endObject() - .endObject().endObject().endObject()); - DocumentMapperParser parser = createIndex("test").mapperService().documentMapperParser(); - DocumentMapper stage1 = parser.parse("person", new CompressedXContent(stage1Mapping)); - String stage2Mapping = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("person").startObject("properties") - .startObject("name").field("type", "text").endObject() - .startObject("age").field("type", "integer").endObject() - .startObject("obj1").startObject("properties").startObject("prop1").field("type", "integer").endObject().endObject() - .endObject() - .endObject().endObject().endObject()); - DocumentMapper stage2 = parser.parse("person", new CompressedXContent(stage2Mapping)); + DocumentMapper stage1 + = createDocumentMapper(mapping(b -> b.startObject("name").field("type", "text").endObject())); + + DocumentMapper stage2 = createDocumentMapper(mapping(b -> { + b.startObject("name").field("type", "text").endObject(); + b.startObject("age").field("type", "integer").endObject(); + b.startObject("obj1"); + { + b.startObject("properties"); + { + b.startObject("prop1").field("type", "integer").endObject(); + } + b.endObject(); + } + b.endObject(); + })); MergeReason reason = randomFrom(MergeReason.MAPPING_UPDATE, MergeReason.INDEX_TEMPLATE); DocumentMapper merged = stage1.merge(stage2.mapping(), reason); + // stage1 mapping should not have been modified assertThat(stage1.mappers().getMapper("age"), nullValue()); assertThat(stage1.mappers().getMapper("obj1.prop1"), nullValue()); @@ -68,14 +74,10 @@ public class DocumentMapperTests extends ESSingleNodeTestCase { } public void testMergeObjectDynamic() throws Exception { - DocumentMapperParser parser = createIndex("test").mapperService().documentMapperParser(); - String objectMapping = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("type1").endObject().endObject()); - DocumentMapper mapper = parser.parse("type1", new CompressedXContent(objectMapping)); + DocumentMapper mapper = createDocumentMapper(mapping(b -> {})); assertNull(mapper.root().dynamic()); - String withDynamicMapping = Strings.toString( - XContentFactory.jsonBuilder().startObject().startObject("type1").field("dynamic", "false").endObject().endObject()); - DocumentMapper withDynamicMapper = parser.parse("type1", new CompressedXContent(withDynamicMapping)); + DocumentMapper withDynamicMapper = createDocumentMapper(topMapping(b -> b.field("dynamic", "false"))); assertThat(withDynamicMapper.root().dynamic(), equalTo(ObjectMapper.Dynamic.FALSE)); DocumentMapper merged = mapper.merge(withDynamicMapper.mapping(), MergeReason.MAPPING_UPDATE); @@ -83,138 +85,115 @@ public class DocumentMapperTests extends ESSingleNodeTestCase { } public void testMergeObjectAndNested() throws Exception { - DocumentMapperParser parser = createIndex("test").mapperService().documentMapperParser(); - String objectMapping = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("type1").startObject("properties") - .startObject("obj").field("type", "object").endObject() - .endObject().endObject().endObject()); - DocumentMapper objectMapper = parser.parse("type1", new CompressedXContent(objectMapping)); - String nestedMapping = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("type1").startObject("properties") - .startObject("obj").field("type", "nested").endObject() - .endObject().endObject().endObject()); - DocumentMapper nestedMapper = parser.parse("type1", new CompressedXContent(nestedMapping)); + DocumentMapper objectMapper + = createDocumentMapper(mapping(b -> b.startObject("obj").field("type", "object").endObject())); + DocumentMapper nestedMapper + = createDocumentMapper(mapping(b -> b.startObject("obj").field("type", "nested").endObject())); MergeReason reason = randomFrom(MergeReason.MAPPING_UPDATE, MergeReason.INDEX_TEMPLATE); - try { - objectMapper.merge(nestedMapper.mapping(), reason); - fail(); - } catch (IllegalArgumentException e) { + { + IllegalArgumentException e = expectThrows(IllegalArgumentException.class, + () -> objectMapper.merge(nestedMapper.mapping(), reason)); assertThat(e.getMessage(), containsString("cannot change object mapping from non-nested to nested")); } - - try { - nestedMapper.merge(objectMapper.mapping(), reason); - fail(); - } catch (IllegalArgumentException e) { + { + IllegalArgumentException e = expectThrows(IllegalArgumentException.class, + () -> nestedMapper.merge(objectMapper.mapping(), reason)); assertThat(e.getMessage(), containsString("cannot change object mapping from nested to non-nested")); } } + @Override + protected IndexAnalyzers createIndexAnalyzers(IndexSettings indexSettings) { + Map analyzers = new HashMap<>(); + analyzers.put("default", new NamedAnalyzer("default", AnalyzerScope.INDEX, new StandardAnalyzer())); + analyzers.put("keyword", new NamedAnalyzer("keyword", AnalyzerScope.INDEX, new KeywordAnalyzer())); + analyzers.put("whitespace", new NamedAnalyzer("whitespace", AnalyzerScope.INDEX, new WhitespaceAnalyzer())); + return new IndexAnalyzers(analyzers, Collections.emptyMap(), Collections.emptyMap()); + } + public void testMergeSearchAnalyzer() throws Exception { - XContentBuilder mapping1 = XContentFactory.jsonBuilder().startObject().startObject("type") - .startObject("properties").startObject("field") - .field("type", "text") - .field("analyzer", "standard") - .field("search_analyzer", "whitespace") - .endObject().endObject() - .endObject().endObject(); - MapperService mapperService = createIndex("test", Settings.EMPTY, "type", mapping1).mapperService(); + MapperService mapperService = createMapperService(fieldMapping(b -> { + b.field("type", "text"); + b.field("analyzer", "default"); + b.field("search_analyzer", "whitespace"); + })); - assertThat(mapperService.fieldType("field").getTextSearchInfo().getSearchAnalyzer().name(), equalTo("whitespace")); + assertThat(mapperService.fieldType("field").getTextSearchInfo().getSearchAnalyzer().name(), + equalTo("whitespace")); - String mapping2 = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("type") - .startObject("properties").startObject("field") - .field("type", "text") - .field("analyzer", "standard") - .field("search_analyzer", "keyword") - .endObject().endObject() - .endObject().endObject()); - - mapperService.merge("type", new CompressedXContent(mapping2), MergeReason.MAPPING_UPDATE); - assertThat(mapperService.fieldType("field").getTextSearchInfo().getSearchAnalyzer().name(), equalTo("keyword")); + merge(mapperService, fieldMapping(b -> { + b.field("type", "text"); + b.field("analyzer", "default"); + b.field("search_analyzer", "keyword"); + })); + assertThat(mapperService.fieldType("field").getTextSearchInfo().getSearchAnalyzer().name(), + equalTo("keyword")); } public void testChangeSearchAnalyzerToDefault() throws Exception { - XContentBuilder mapping1 = XContentFactory.jsonBuilder().startObject().startObject("type") - .startObject("properties").startObject("field") - .field("type", "text") - .field("analyzer", "standard") - .field("search_analyzer", "whitespace") - .endObject().endObject() - .endObject().endObject(); - MapperService mapperService = createIndex("test", Settings.EMPTY, "type", mapping1).mapperService(); - assertThat(mapperService.fieldType("field").getTextSearchInfo().getSearchAnalyzer().name(), equalTo("whitespace")); + MapperService mapperService = createMapperService(fieldMapping(b -> { + b.field("type", "text"); + b.field("analyzer", "default"); + b.field("search_analyzer", "whitespace"); + })); - String mapping2 = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("type") - .startObject("properties").startObject("field") - .field("type", "text") - .field("analyzer", "standard") - .endObject().endObject() - .endObject().endObject()); + assertThat(mapperService.fieldType("field").getTextSearchInfo().getSearchAnalyzer().name(), + equalTo("whitespace")); - mapperService.merge("type", new CompressedXContent(mapping2), MergeReason.MAPPING_UPDATE); - assertThat(mapperService.fieldType("field").getTextSearchInfo().getSearchAnalyzer().name(), equalTo("standard")); + merge(mapperService, fieldMapping(b -> { + b.field("type", "text"); + b.field("analyzer", "default"); + })); + + assertThat(mapperService.fieldType("field").getTextSearchInfo().getSearchAnalyzer().name(), + equalTo("default")); } public void testConcurrentMergeTest() throws Throwable { - final MapperService mapperService = createIndex("test").mapperService(); - MergeReason reason = randomFrom(MergeReason.MAPPING_UPDATE, MergeReason.INDEX_TEMPLATE); - mapperService.merge("test", new CompressedXContent("{\"test\":{}}"), reason); - final DocumentMapper documentMapper = mapperService.documentMapper("test"); - MappingLookup dfm = documentMapper.mappers(); - try { - assertNotNull(dfm.indexAnalyzer().tokenStream("non_existing_field", "foo")); - fail(); - } catch (IllegalArgumentException e) { - // ok that's expected - } + final MapperService mapperService = createMapperService(mapping(b -> {})); + final DocumentMapper documentMapper = mapperService.documentMapper(); + + expectThrows(IllegalArgumentException.class, + () -> documentMapper.mappers().indexAnalyzer().tokenStream("non_existing_field", "foo")); final AtomicBoolean stopped = new AtomicBoolean(false); final CyclicBarrier barrier = new CyclicBarrier(2); final AtomicReference lastIntroducedFieldName = new AtomicReference<>(); final AtomicReference error = new AtomicReference<>(); - final Thread updater = new Thread() { - @Override - public void run() { - try { - barrier.await(); - for (int i = 0; i < 200 && stopped.get() == false; i++) { - final String fieldName = Integer.toString(i); - ParsedDocument doc = documentMapper.parse(new SourceToParse("test", - "test", - fieldName, - new BytesArray("{ \"" + fieldName + "\" : \"test\" }"), - XContentType.JSON)); - Mapping update = doc.dynamicMappingsUpdate(); - assert update != null; - lastIntroducedFieldName.set(fieldName); - mapperService.merge("test", new CompressedXContent(update.toString()), MergeReason.MAPPING_UPDATE); - } - } catch (Exception e) { - error.set(e); - } finally { - stopped.set(true); + final Thread updater = new Thread(() -> { + try { + barrier.await(); + for (int i = 0; i < 200 && stopped.get() == false; i++) { + final String fieldName = Integer.toString(i); + ParsedDocument doc = documentMapper.parse(source(b -> b.field(fieldName, "test"))); + Mapping update = doc.dynamicMappingsUpdate(); + assert update != null; + lastIntroducedFieldName.set(fieldName); + mapperService.merge("_doc", new CompressedXContent(update.toString()), MergeReason.MAPPING_UPDATE); } + } catch (Exception e) { + error.set(e); + } finally { + stopped.set(true); } - }; + }); updater.start(); try { barrier.await(); while(stopped.get() == false) { final String fieldName = lastIntroducedFieldName.get(); - final BytesReference source = new BytesArray("{ \"" + fieldName + "\" : \"test\" }"); - ParsedDocument parsedDoc = documentMapper.parse(new SourceToParse("test", - "test", - "random", - source, - XContentType.JSON)); + if (fieldName == null) { + continue; + } + ParsedDocument parsedDoc = mapperService.documentMapper().parse(source(b -> b.field(fieldName, "test"))); if (parsedDoc.dynamicMappingsUpdate() != null) { // not in the mapping yet, try again continue; } - dfm = documentMapper.mappers(); - assertNotNull(dfm.indexAnalyzer().tokenStream(fieldName, "foo")); + assertNotNull(mapperService.indexAnalyzer().tokenStream(fieldName, "foo")); } } finally { stopped.set(true); @@ -226,133 +205,82 @@ public class DocumentMapperTests extends ESSingleNodeTestCase { } public void testDoNotRepeatOriginalMapping() throws IOException { - MergeReason reason = randomFrom(MergeReason.MAPPING_UPDATE, MergeReason.INDEX_TEMPLATE); - CompressedXContent mapping = new CompressedXContent(BytesReference.bytes(XContentFactory.jsonBuilder().startObject() - .startObject("type") - .startObject("_source") - .field("enabled", false) - .endObject() - .endObject().endObject())); - MapperService mapperService = createIndex("test").mapperService(); - mapperService.merge("type", mapping, reason); + MapperService mapperService + = createMapperService(topMapping(b -> b.startObject("_source").field("enabled", false).endObject())); - CompressedXContent update = new CompressedXContent(BytesReference.bytes(XContentFactory.jsonBuilder().startObject() - .startObject("type") - .startObject("properties") - .startObject("foo") - .field("type", "text") - .endObject() - .endObject() - .endObject().endObject())); - DocumentMapper mapper = mapperService.merge("type", update, reason); + merge(mapperService, fieldMapping(b -> b.field("type", "text"))); - assertNotNull(mapper.mappers().getMapper("foo")); - assertFalse(mapper.sourceMapper().enabled()); + assertNotNull(mapperService.documentMapper().mappers().getMapper("field")); + assertFalse(mapperService.documentMapper().sourceMapper().enabled()); } public void testMergeMetadataFieldsForIndexTemplates() throws IOException { - CompressedXContent mapping = new CompressedXContent(BytesReference.bytes(XContentFactory.jsonBuilder().startObject() - .startObject("type") - .startObject("_source") - .field("enabled", false) - .endObject() - .endObject().endObject())); - MapperService mapperService = createIndex("test").mapperService(); - mapperService.merge("type", mapping, MergeReason.INDEX_TEMPLATE); + MapperService mapperService + = createMapperService(topMapping(b -> b.startObject("_source").field("enabled", false).endObject())); - CompressedXContent update = new CompressedXContent(BytesReference.bytes(XContentFactory.jsonBuilder().startObject() - .startObject("type") - .startObject("_source") - .field("enabled", true) - .endObject() - .endObject().endObject())); - DocumentMapper mapper = mapperService.merge("type", update, MergeReason.INDEX_TEMPLATE); + merge(mapperService, MergeReason.INDEX_TEMPLATE, + topMapping(b -> b.startObject("_source").field("enabled", true).endObject())); + DocumentMapper mapper = mapperService.documentMapper(); assertTrue(mapper.sourceMapper().enabled()); } public void testMergeMeta() throws IOException { - DocumentMapperParser parser = createIndex("test").mapperService().documentMapperParser(); - String initMapping = Strings - .toString(XContentFactory.jsonBuilder() - .startObject() - .startObject("test") - .startObject("_meta") - .field("foo").value("bar") - .endObject() - .endObject() - .endObject()); - DocumentMapper initMapper = parser.parse("test", new CompressedXContent(initMapping)); + DocumentMapper initMapper + = createDocumentMapper(topMapping(b -> b.startObject("_meta").field("foo", "bar").endObject())); assertThat(initMapper.meta().get("foo"), equalTo("bar")); - String updateMapping = Strings - .toString(XContentFactory.jsonBuilder() - .startObject() - .startObject("test") - .startObject("properties") - .startObject("name").field("type", "text").endObject() - .endObject() - .endObject() - .endObject()); - DocumentMapper updatedMapper = parser.parse("test", new CompressedXContent(updateMapping)); + DocumentMapper updatedMapper = createDocumentMapper(fieldMapping(b -> b.field("type", "text"))); DocumentMapper mergedMapper = initMapper.merge(updatedMapper.mapping(), MergeReason.MAPPING_UPDATE); assertThat(mergedMapper.meta().get("foo"), equalTo("bar")); - updateMapping = Strings - .toString(XContentFactory.jsonBuilder() - .startObject() - .startObject("test") - .startObject("_meta") - .field("foo").value("new_bar") - .endObject() - .endObject() - .endObject()); - updatedMapper = parser.parse("test", new CompressedXContent(updateMapping)); + updatedMapper + = createDocumentMapper(topMapping(b -> b.startObject("_meta").field("foo", "new_bar").endObject())); mergedMapper = initMapper.merge(updatedMapper.mapping(), MergeReason.MAPPING_UPDATE); assertThat(mergedMapper.meta().get("foo"), equalTo("new_bar")); } public void testMergeMetaForIndexTemplate() throws IOException { - DocumentMapperParser parser = createIndex("test").mapperService().documentMapperParser(); - String initMapping = Strings.toString(XContentFactory.jsonBuilder().startObject() - .startObject("_meta") - .field("field", "value") - .startObject("object") - .field("field1", "value1") - .field("field2", "value2") - .endObject() - .endObject() - .endObject()); - DocumentMapper initMapper = parser.parse(MapperService.SINGLE_MAPPING_NAME, new CompressedXContent(initMapping)); + DocumentMapper initMapper = createDocumentMapper(topMapping(b -> { + b.startObject("_meta"); + { + b.field("field", "value"); + b.startObject("object"); + { + b.field("field1", "value1"); + b.field("field2", "value2"); + } + b.endObject(); + } + b.endObject(); + })); Map expected = org.elasticsearch.common.collect.Map.of( "field", "value", "object", org.elasticsearch.common.collect.Map.of("field1", "value1", "field2", "value2")); assertThat(initMapper.meta(), equalTo(expected)); - String updateMapping = Strings.toString(XContentFactory.jsonBuilder().startObject() - .startObject("properties") - .startObject("name").field("type", "text").endObject() - .endObject() - .endObject()); - DocumentMapper updatedMapper = parser.parse(MapperService.SINGLE_MAPPING_NAME, new CompressedXContent(updateMapping)); + DocumentMapper updatedMapper = createDocumentMapper(fieldMapping(b -> b.field("type", "text"))); DocumentMapper mergedMapper = initMapper.merge(updatedMapper.mapping(), MergeReason.INDEX_TEMPLATE); assertThat(mergedMapper.meta(), equalTo(expected)); - updateMapping = Strings.toString(XContentFactory.jsonBuilder().startObject() - .startObject("_meta") - .field("field", "value") - .startObject("object") - .field("field2", "new_value") - .field("field3", "value3") - .endObject() - .endObject() - .endObject()); - updatedMapper = parser.parse(MapperService.SINGLE_MAPPING_NAME, new CompressedXContent(updateMapping)); + updatedMapper = createDocumentMapper(topMapping(b -> { + b.startObject("_meta"); + { + b.field("field", "value"); + b.startObject("object"); + { + b.field("field2", "new_value"); + b.field("field3", "value3"); + } + b.endObject(); + } + b.endObject(); + })); mergedMapper = mergedMapper.merge(updatedMapper.mapping(), MergeReason.INDEX_TEMPLATE); expected = org.elasticsearch.common.collect.Map.of( diff --git a/server/src/test/java/org/elasticsearch/index/mapper/DocumentParserTests.java b/server/src/test/java/org/elasticsearch/index/mapper/DocumentParserTests.java index f96d518fadd..e819bc1f862 100644 --- a/server/src/test/java/org/elasticsearch/index/mapper/DocumentParserTests.java +++ b/server/src/test/java/org/elasticsearch/index/mapper/DocumentParserTests.java @@ -26,29 +26,20 @@ import org.elasticsearch.cluster.metadata.IndexMetadata; import org.elasticsearch.common.Strings; import org.elasticsearch.common.bytes.BytesArray; import org.elasticsearch.common.bytes.BytesReference; -import org.elasticsearch.common.compress.CompressedXContent; import org.elasticsearch.common.settings.Settings; -import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentFactory; import org.elasticsearch.common.xcontent.XContentType; -import org.elasticsearch.index.IndexService; import org.elasticsearch.index.IndexSettings; import org.elasticsearch.index.mapper.ParseContext.Document; -import org.elasticsearch.plugins.Plugin; -import org.elasticsearch.test.ESSingleNodeTestCase; -import org.elasticsearch.test.TestGeoShapeFieldMapperPlugin; -import org.elasticsearch.test.InternalSettingsPlugin; import java.io.IOException; import java.math.BigDecimal; import java.math.BigInteger; import java.nio.charset.StandardCharsets; import java.util.ArrayList; -import java.util.Collection; import java.util.Collections; import java.util.List; -import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder; import static org.elasticsearch.test.StreamsUtils.copyToBytesFromClasspath; import static org.elasticsearch.test.StreamsUtils.copyToStringFromClasspath; import static org.hamcrest.Matchers.containsString; @@ -57,103 +48,89 @@ import static org.hamcrest.Matchers.instanceOf; import static org.hamcrest.Matchers.not; import static org.hamcrest.Matchers.notNullValue; -// TODO: make this a real unit test -public class DocumentParserTests extends ESSingleNodeTestCase { - - @Override - protected Collection> getPlugins() { - return pluginList(InternalSettingsPlugin.class, TestGeoShapeFieldMapperPlugin.class); - } +public class DocumentParserTests extends MapperServiceTestCase { public void testFieldDisabled() throws Exception { - DocumentMapperParser mapperParser = createIndex("test").mapperService().documentMapperParser(); - String mapping = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("type").startObject("properties") - .startObject("foo").field("enabled", false).endObject() - .startObject("bar").field("type", "integer").endObject() - .endObject().endObject().endObject()); - DocumentMapper mapper = mapperParser.parse("type", new CompressedXContent(mapping)); + DocumentMapper mapper = createDocumentMapper(mapping(b -> { + b.startObject("foo").field("enabled", false).endObject(); + b.startObject("bar").field("type", "integer").endObject(); + })); - BytesReference bytes = BytesReference.bytes(XContentFactory.jsonBuilder() - .startObject() - .field("foo", "1234") - .field("bar", 10) - .endObject()); - ParsedDocument doc = mapper.parse(new SourceToParse("test", "type", "1", bytes, XContentType.JSON)); + ParsedDocument doc = mapper.parse(source(b -> { + b.field("foo", "1234"); + b.field("bar", 10); + })); assertNull(doc.rootDoc().getField("foo")); assertNotNull(doc.rootDoc().getField("bar")); assertNotNull(doc.rootDoc().getField(IdFieldMapper.NAME)); } public void testDotsWithFieldDisabled() throws IOException { - DocumentMapperParser mapperParser = createIndex("test").mapperService().documentMapperParser(); - String mapping = Strings.toString(jsonBuilder().startObject().startObject("type").startObject("properties") - .startObject("foo").field("enabled", false).endObject() - .endObject().endObject().endObject()); - DocumentMapper mapper = mapperParser.parse("type", new CompressedXContent(mapping)); + DocumentMapper mapper = createDocumentMapper(fieldMapping(b -> b.field("enabled", false))); { - BytesReference bytes = BytesReference.bytes(jsonBuilder() - .startObject() - .field("foo.bar", 111) - .endObject()); - ParsedDocument doc = mapper.parse(new SourceToParse("test", "type", "1", bytes, XContentType.JSON)); - assertNull(doc.rootDoc().getField("foo")); + ParsedDocument doc = mapper.parse(source(b -> b.field("field.bar", 111))); + assertNull(doc.rootDoc().getField("field")); assertNull(doc.rootDoc().getField("bar")); - assertNull(doc.rootDoc().getField("foo.bar")); + assertNull(doc.rootDoc().getField("field.bar")); } { - BytesReference bytes = BytesReference.bytes(jsonBuilder() - .startObject() - .field("foo.bar", new int[]{1, 2, 3}) - .endObject()); - ParsedDocument doc = mapper.parse(new SourceToParse("test", "type", "1", bytes, XContentType.JSON)); - assertNull(doc.rootDoc().getField("foo")); + ParsedDocument doc = mapper.parse(source(b -> b.field("field.bar", new int[]{1, 2, 3}))); + assertNull(doc.rootDoc().getField("field")); assertNull(doc.rootDoc().getField("bar")); - assertNull(doc.rootDoc().getField("foo.bar")); + assertNull(doc.rootDoc().getField("field.bar")); } { - BytesReference bytes = BytesReference.bytes(jsonBuilder() - .startObject() - .field("foo.bar", Collections.singletonMap("key", "value")) - .endObject()); - ParsedDocument doc = mapper.parse(new SourceToParse("test", "type", "1", bytes, XContentType.JSON)); - assertNull(doc.rootDoc().getField("foo")); + ParsedDocument doc = mapper.parse(source(b -> b.field("field.bar", Collections.singletonMap("key", "value")))); + assertNull(doc.rootDoc().getField("field")); assertNull(doc.rootDoc().getField("bar")); - assertNull(doc.rootDoc().getField("foo.bar")); + assertNull(doc.rootDoc().getField("field.bar")); } { - BytesReference bytes = BytesReference.bytes(jsonBuilder() - .startObject() - .field("foo.bar", "string value") - .field("blub", 222) - .endObject()); - ParsedDocument doc = mapper.parse(new SourceToParse("test", "type", "1", bytes, XContentType.JSON)); - assertNull(doc.rootDoc().getField("foo")); + ParsedDocument doc = mapper.parse(source(b -> { + b.field("field.bar", "string value"); + b.field("blub", 222); + })); + assertNull(doc.rootDoc().getField("field")); assertNull(doc.rootDoc().getField("bar")); - assertNull(doc.rootDoc().getField("foo.bar")); + assertNull(doc.rootDoc().getField("field.bar")); assertNotNull(doc.rootDoc().getField("blub")); } } public void testDotsWithExistingMapper() throws Exception { - DocumentMapperParser mapperParser = createIndex("test").mapperService().documentMapperParser(); - String mapping = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("type").startObject("properties") - .startObject("foo").startObject("properties") - .startObject("bar").startObject("properties") - .startObject("baz").field("type", "integer") - .endObject().endObject().endObject().endObject().endObject().endObject().endObject().endObject()); - DocumentMapper mapper = mapperParser.parse("type", new CompressedXContent(mapping)); + DocumentMapper mapper = createDocumentMapper(mapping(b -> { + b.startObject("foo"); + { + b.startObject("properties"); + { + b.startObject("bar"); + { + b.startObject("properties"); + { + b.startObject("baz").field("type", "integer").endObject(); + } + b.endObject(); + } + b.endObject(); + } + b.endObject(); + } + b.endObject(); + })); - BytesReference bytes = BytesReference.bytes(XContentFactory.jsonBuilder() - .startObject() - .field("foo.bar.baz", 123) - .startObject("foo") - .field("bar.baz", 456) - .endObject() - .startObject("foo.bar") - .field("baz", 789) - .endObject() - .endObject()); - ParsedDocument doc = mapper.parse(new SourceToParse("test", "type", "1", bytes, XContentType.JSON)); + ParsedDocument doc = mapper.parse(source(b -> { + b.field("foo.bar.baz", 123); + b.startObject("foo"); + { + b.field("bar.baz", 456); + } + b.endObject(); + b.startObject("foo.bar"); + { + b.field("baz", 789); + } + b.endObject(); + })); assertNull(doc.dynamicMappingsUpdate()); // no update! IndexableField[] fields = doc.rootDoc().getFields("foo.bar.baz"); @@ -167,125 +144,89 @@ public class DocumentParserTests extends ESSingleNodeTestCase { } public void testDotsWithExistingNestedMapper() throws Exception { - DocumentMapperParser mapperParser = createIndex("test").mapperService().documentMapperParser(); - String mapping = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("type").startObject("properties") - .startObject("foo").field("type", "nested").startObject("properties") - .startObject("bar").field("type", "integer") - .endObject().endObject().endObject().endObject().endObject().endObject()); - DocumentMapper mapper = mapperParser.parse("type", new CompressedXContent(mapping)); + DocumentMapper mapper = createDocumentMapper(fieldMapping(b -> { + b.field("type", "nested"); + b.startObject("properties"); + { + b.startObject("bar").field("type", "integer").endObject(); + } + b.endObject(); + })); - BytesReference bytes = BytesReference.bytes(XContentFactory.jsonBuilder() - .startObject() - .field("foo.bar", 123) - .endObject()); MapperParsingException e = expectThrows(MapperParsingException.class, - () -> mapper.parse(new SourceToParse("test", "type", "1", bytes, XContentType.JSON))); + () -> mapper.parse(source(b -> b.field("field.bar", 123)))); assertEquals( - "Cannot add a value for field [foo.bar] since one of the intermediate objects is mapped as a nested object: [foo]", + "Cannot add a value for field [field.bar] since one of the intermediate objects is mapped as a nested object: [field]", e.getMessage()); } public void testUnexpectedFieldMappingType() throws Exception { - DocumentMapperParser mapperParser = createIndex("test").mapperService().documentMapperParser(); - String mapping = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("type").startObject("properties") - .startObject("foo").field("type", "long").endObject() - .startObject("bar").field("type", "boolean").endObject() - .startObject("geo").field("type", "geo_shape").endObject() - .endObject().endObject().endObject()); - DocumentMapper mapper = mapperParser.parse("type", new CompressedXContent(mapping)); + DocumentMapper mapper = createDocumentMapper(mapping(b -> { + b.startObject("foo").field("type", "long").endObject(); + b.startObject("bar").field("type", "boolean").endObject(); + })); { - BytesReference bytes = BytesReference.bytes(XContentFactory.jsonBuilder().startObject().field("foo", true) - .endObject()); MapperException exception = expectThrows(MapperException.class, - () -> mapper.parse(new SourceToParse("test", "type", "1", bytes, XContentType.JSON))); + () -> mapper.parse(source(b -> b.field("foo", true)))); assertThat(exception.getMessage(), containsString("failed to parse field [foo] of type [long] in document with id '1'")); } { - BytesReference bytes = BytesReference.bytes(XContentFactory.jsonBuilder().startObject().field("bar", "bar") - .endObject()); MapperException exception = expectThrows(MapperException.class, - () -> mapper.parse(new SourceToParse("test", "type", "2", bytes, XContentType.JSON))); - assertThat(exception.getMessage(), containsString("failed to parse field [bar] of type [boolean] in document with id '2'")); + () -> mapper.parse(source(b -> b.field("bar", "bar")))); + assertThat(exception.getMessage(), containsString("failed to parse field [bar] of type [boolean] in document with id '1'")); } - { - BytesReference bytes = BytesReference.bytes(XContentFactory.jsonBuilder().startObject().field("geo", 123) - .endObject()); - MapperException exception = expectThrows(MapperException.class, - () -> mapper.parse(new SourceToParse("test", "type", "2", bytes, XContentType.JSON))); - assertThat(exception.getMessage(), containsString("failed to parse field [geo]")); - } - } public void testDotsWithDynamicNestedMapper() throws Exception { - DocumentMapperParser mapperParser = createIndex("test").mapperService().documentMapperParser(); - String mapping = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("type") - .startArray("dynamic_templates") - .startObject() - .startObject("objects_as_nested") - .field("match_mapping_type", "object") - .startObject("mapping") - .field("type", "nested") - .endObject() - .endObject() - .endObject() - .endArray().endObject().endObject()); - DocumentMapper mapper = mapperParser.parse("type", new CompressedXContent(mapping)); + DocumentMapper mapper = createDocumentMapper(topMapping(b -> { + b.startArray("dynamic_templates"); + { + b.startObject(); + { + b.startObject("objects_as_nested"); + { + b.field("match_mapping_type", "object"); + b.startObject("mapping").field("type", "nested").endObject(); + } + b.endObject(); + } + b.endObject(); + } + b.endArray(); + })); - BytesReference bytes = BytesReference.bytes(XContentFactory.jsonBuilder() - .startObject() - .field("foo.bar",42) - .endObject()); MapperParsingException e = expectThrows(MapperParsingException.class, - () -> mapper.parse(new SourceToParse("test", "type", "1", bytes, XContentType.JSON))); + () -> mapper.parse(source(b -> b.field("foo.bar", 42)))); assertEquals( "It is forbidden to create dynamic nested objects ([foo]) through `copy_to` or dots in field names", e.getMessage()); } public void testNestedHaveIdAndTypeFields() throws Exception { - DocumentMapperParser mapperParser2 = createIndex("index2").mapperService().documentMapperParser(); - XContentBuilder mapping = XContentFactory.jsonBuilder().startObject().startObject("type").startObject("properties"); - { - mapping.startObject("foo"); - mapping.field("type", "nested"); + DocumentMapper mapper = createDocumentMapper(mapping(b -> { + b.startObject("foo"); { - mapping.startObject("properties"); + b.field("type", "nested"); + b.startObject("properties"); { - - mapping.startObject("bar"); - mapping.field("type", "keyword"); - mapping.endObject(); + b.startObject("bar").field("type", "keyword").endObject(); } - mapping.endObject(); + b.endObject(); } - mapping.endObject(); - } - { - mapping.startObject("baz"); - mapping.field("type", "keyword"); - mapping.endObject(); - } - mapping.endObject().endObject().endObject(); - DocumentMapper mapper = mapperParser2.parse("type", new CompressedXContent(Strings.toString(mapping))); - - XContentBuilder doc = XContentFactory.jsonBuilder().startObject(); - { - doc.startArray("foo"); - { - doc.startObject(); - doc.field("bar", "value1"); - doc.endObject(); - } - doc.endArray(); - doc.field("baz", "value2"); - } - doc.endObject(); + b.endObject(); + b.startObject("baz").field("type", "keyword").endObject(); + })); // Verify in the case where only a single type is allowed that the _id field is added to nested documents: - ParsedDocument result = mapper.parse(new SourceToParse("index2", "type", "1", - BytesReference.bytes(doc), XContentType.JSON)); + ParsedDocument result = mapper.parse(source(b -> { + b.startArray("foo"); + { + b.startObject().field("bar", "value1").endObject(); + } + b.endArray(); + b.field("baz", "value2"); + })); assertEquals(2, result.docs().size()); // Nested document: assertNotNull(result.docs().get(0).getField(IdFieldMapper.NAME)); @@ -303,78 +244,100 @@ public class DocumentParserTests extends ESSingleNodeTestCase { } public void testPropagateDynamicWithExistingMapper() throws Exception { - DocumentMapperParser mapperParser = createIndex("test").mapperService().documentMapperParser(); - String mapping = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("type") - .field("dynamic", false) - .startObject("properties") - .startObject("foo") - .field("type", "object") - .field("dynamic", true) - .startObject("properties") - .endObject().endObject().endObject().endObject().endObject()); - DocumentMapper mapper = mapperParser.parse("type", new CompressedXContent(mapping)); - BytesReference bytes = BytesReference.bytes(XContentFactory.jsonBuilder() - .startObject().startObject("foo") - .field("bar", "something") - .endObject().endObject()); - ParsedDocument doc = mapper.parse(new SourceToParse("test", "type", "1", bytes, XContentType.JSON)); + DocumentMapper mapper = createDocumentMapper(topMapping(b -> { + b.field("dynamic", false); + b.startObject("properties"); + { + b.startObject("foo"); + { + b.field("type", "object"); + b.field("dynamic", true); + b.startObject("properties").endObject(); + } + b.endObject(); + } + b.endObject(); + })); + ParsedDocument doc = mapper.parse(source(b -> b.startObject("foo").field("bar", "something").endObject())); assertNotNull(doc.dynamicMappingsUpdate()); assertNotNull(doc.rootDoc().getField("foo.bar")); } public void testPropagateDynamicWithDynamicMapper() throws Exception { - DocumentMapperParser mapperParser = createIndex("test").mapperService().documentMapperParser(); - String mapping = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("type") - .field("dynamic", false) - .startObject("properties") - .startObject("foo") - .field("type", "object") - .field("dynamic", true) - .startObject("properties") - .endObject().endObject().endObject().endObject().endObject()); - DocumentMapper mapper = mapperParser.parse("type", new CompressedXContent(mapping)); - BytesReference bytes = BytesReference.bytes(XContentFactory.jsonBuilder() - .startObject().startObject("foo").startObject("bar") - .field("baz", "something") - .endObject().endObject().endObject()); - ParsedDocument doc = mapper.parse(new SourceToParse("test", "type", "1", bytes, XContentType.JSON)); + DocumentMapper mapper = createDocumentMapper(topMapping(b -> { + b.field("dynamic", false); + b.startObject("properties"); + { + b.startObject("foo"); + { + b.field("type", "object"); + b.field("dynamic", true); + b.startObject("properties").endObject(); + } + b.endObject(); + } + b.endObject(); + })); + ParsedDocument doc = mapper.parse(source(b -> { + b.startObject("foo"); + { + b.startObject("bar").field("baz", "something").endObject(); + } + b.endObject(); + })); assertNotNull(doc.dynamicMappingsUpdate()); assertNotNull(doc.rootDoc().getField("foo.bar.baz")); } public void testDynamicRootFallback() throws Exception { - DocumentMapperParser mapperParser = createIndex("test").mapperService().documentMapperParser(); - String mapping = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("type") - .field("dynamic", false) - .startObject("properties") - .startObject("foo") - .field("type", "object") - .startObject("properties") - .endObject().endObject().endObject().endObject().endObject()); - DocumentMapper mapper = mapperParser.parse("type", new CompressedXContent(mapping)); - BytesReference bytes = BytesReference.bytes(XContentFactory.jsonBuilder() - .startObject().startObject("foo") - .field("bar", "something") - .endObject().endObject()); - ParsedDocument doc = mapper.parse(new SourceToParse("test", "type", "1", bytes, XContentType.JSON)); + DocumentMapper mapper = createDocumentMapper(topMapping(b -> { + b.field("dynamic", false); + b.startObject("properties"); + { + b.startObject("foo"); + { + b.field("type", "object"); + b.startObject("properties").endObject(); + } + b.endObject(); + } + b.endObject(); + })); + ParsedDocument doc = mapper.parse(source(b -> b.startObject("foo").field("bar", "something").endObject())); assertNull(doc.dynamicMappingsUpdate()); assertNull(doc.rootDoc().getField("foo.bar")); } - DocumentMapper createDummyMapping(MapperService mapperService) throws Exception { - String mapping = Strings.toString(jsonBuilder().startObject().startObject("type").startObject("properties") - .startObject("y").field("type", "object").endObject() - .startObject("x").startObject("properties") - .startObject("subx").field("type", "object").startObject("properties") - .startObject("subsubx").field("type", "object") - .endObject().endObject().endObject().endObject().endObject().endObject().endObject().endObject()); + DocumentMapper createDummyMapping() throws Exception { + return createMapperService().documentMapper(); + } - DocumentMapper defaultMapper = mapperService.documentMapperParser().parse("type", new CompressedXContent(mapping)); - return defaultMapper; + MapperService createMapperService() throws Exception { + return createMapperService(mapping(b -> { + b.startObject("y").field("type", "object").endObject(); + b.startObject("x"); + { + b.startObject("properties"); + { + b.startObject("subx"); + { + b.field("type", "object"); + b.startObject("properties"); + { + b.startObject("subsubx").field("type", "object").endObject(); + } + b.endObject(); + } + b.endObject(); + } + b.endObject(); + } + b.endObject(); + })); } // creates an object mapper, which is about 100x harder than it should be.... - ObjectMapper createObjectMapper(MapperService mapperService, String name) throws Exception { + ObjectMapper createObjectMapper(MapperService mapperService, String name) { IndexMetadata build = IndexMetadata.builder("") .settings(Settings.builder().put(IndexMetadata.SETTING_VERSION_CREATED, Version.CURRENT)) .numberOfShards(1).numberOfReplicas(0).build(); @@ -385,27 +348,29 @@ public class DocumentParserTests extends ESSingleNodeTestCase { for (int i = 0; i < nameParts.length - 1; ++i) { context.path().add(nameParts[i]); } - Mapper.Builder builder = new ObjectMapper.Builder(nameParts[nameParts.length - 1]).enabled(true); + Mapper.Builder builder = new ObjectMapper.Builder<>(nameParts[nameParts.length - 1]).enabled(true); Mapper.BuilderContext builderContext = new Mapper.BuilderContext(context.indexSettings().getSettings(), context.path()); return (ObjectMapper)builder.build(builderContext); } public void testEmptyMappingUpdate() throws Exception { - DocumentMapper docMapper = createDummyMapping(createIndex("test").mapperService()); + DocumentMapper docMapper = createDummyMapping(); assertNull(DocumentParser.createDynamicUpdate(docMapper.mapping(), docMapper, Collections.emptyList())); } public void testSingleMappingUpdate() throws Exception { - DocumentMapper docMapper = createDummyMapping(createIndex("test").mapperService()); + DocumentMapper docMapper = createDummyMapping(); List updates = Collections.singletonList(new MockFieldMapper("foo")); Mapping mapping = DocumentParser.createDynamicUpdate(docMapper.mapping(), docMapper, updates); + assertNotNull(mapping); assertNotNull(mapping.root().getMapper("foo")); } public void testSubfieldMappingUpdate() throws Exception { - DocumentMapper docMapper = createDummyMapping(createIndex("test").mapperService()); + DocumentMapper docMapper = createDummyMapping(); List updates = Collections.singletonList(new MockFieldMapper("x.foo")); Mapping mapping = DocumentParser.createDynamicUpdate(docMapper.mapping(), docMapper, updates); + assertNotNull(mapping); Mapper xMapper = mapping.root().getMapper("x"); assertNotNull(xMapper); assertTrue(xMapper instanceof ObjectMapper); @@ -414,11 +379,12 @@ public class DocumentParserTests extends ESSingleNodeTestCase { } public void testMultipleSubfieldMappingUpdate() throws Exception { - DocumentMapper docMapper = createDummyMapping(createIndex("test").mapperService()); + DocumentMapper docMapper = createDummyMapping(); List updates = new ArrayList<>(); updates.add(new MockFieldMapper("x.foo")); updates.add(new MockFieldMapper("x.bar")); Mapping mapping = DocumentParser.createDynamicUpdate(docMapper.mapping(), docMapper, updates); + assertNotNull(mapping); Mapper xMapper = mapping.root().getMapper("x"); assertNotNull(xMapper); assertTrue(xMapper instanceof ObjectMapper); @@ -428,9 +394,10 @@ public class DocumentParserTests extends ESSingleNodeTestCase { } public void testDeepSubfieldMappingUpdate() throws Exception { - DocumentMapper docMapper = createDummyMapping(createIndex("test").mapperService()); + DocumentMapper docMapper = createDummyMapping(); List updates = Collections.singletonList(new MockFieldMapper("x.subx.foo")); Mapping mapping = DocumentParser.createDynamicUpdate(docMapper.mapping(), docMapper, updates); + assertNotNull(mapping); Mapper xMapper = mapping.root().getMapper("x"); assertNotNull(xMapper); assertTrue(xMapper instanceof ObjectMapper); @@ -441,11 +408,12 @@ public class DocumentParserTests extends ESSingleNodeTestCase { } public void testDeepSubfieldAfterSubfieldMappingUpdate() throws Exception { - DocumentMapper docMapper = createDummyMapping(createIndex("test").mapperService()); + DocumentMapper docMapper = createDummyMapping(); List updates = new ArrayList<>(); updates.add(new MockFieldMapper("x.a")); updates.add(new MockFieldMapper("x.subx.b")); Mapping mapping = DocumentParser.createDynamicUpdate(docMapper.mapping(), docMapper, updates); + assertNotNull(mapping); Mapper xMapper = mapping.root().getMapper("x"); assertNotNull(xMapper); assertTrue(xMapper instanceof ObjectMapper); @@ -456,14 +424,15 @@ public class DocumentParserTests extends ESSingleNodeTestCase { } public void testObjectMappingUpdate() throws Exception { - MapperService mapperService = createIndex("test").mapperService(); - DocumentMapper docMapper = createDummyMapping(mapperService); + MapperService mapperService = createMapperService(); + DocumentMapper docMapper = mapperService.documentMapper(); List updates = new ArrayList<>(); updates.add(createObjectMapper(mapperService, "foo")); updates.add(createObjectMapper(mapperService, "foo.bar")); updates.add(new MockFieldMapper("foo.bar.baz")); updates.add(new MockFieldMapper("foo.field")); Mapping mapping = DocumentParser.createDynamicUpdate(docMapper.mapping(), docMapper, updates); + assertNotNull(mapping); Mapper fooMapper = mapping.root().getMapper("foo"); assertNotNull(fooMapper); assertTrue(fooMapper instanceof ObjectMapper); @@ -474,267 +443,198 @@ public class DocumentParserTests extends ESSingleNodeTestCase { } public void testDynamicGeoPointArrayWithTemplate() throws Exception { - DocumentMapperParser mapperParser = createIndex("test").mapperService().documentMapperParser(); - String mapping = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("type") - .startArray("dynamic_templates").startObject().startObject("georule") - .field("match", "foo*") - .startObject("mapping").field("type", "geo_point").field("doc_values", false).endObject() - .endObject().endObject().endArray().endObject().endObject()); - DocumentMapper mapper = mapperParser.parse("type", new CompressedXContent(mapping)); + DocumentMapper mapper = createDocumentMapper(topMapping(b -> { + b.startArray("dynamic_templates"); + { + b.startObject(); + { + b.startObject("georule"); + { + b.field("match", "foo*"); + b.startObject("mapping"); + { + b.field("type", "geo_point"); + b.field("doc_values", false); + } + b.endObject(); + } + b.endObject(); + } + b.endObject(); + } + b.endArray(); + })); - BytesReference bytes = BytesReference.bytes(XContentFactory.jsonBuilder() - .startObject().startArray("foo") - .startArray().value(0).value(0).endArray() - .startArray().value(1).value(1).endArray() - .endArray().endObject()); - ParsedDocument doc = mapper.parse(new SourceToParse("test", "type", "1", bytes, XContentType.JSON)); + ParsedDocument doc = mapper.parse(source(b -> { + b.startArray("foo"); + { + b.startArray().value(0).value(0).endArray(); + b.startArray().value(1).value(1).endArray(); + } + b.endArray(); + })); assertEquals(2, doc.rootDoc().getFields("foo").length); } public void testDynamicLongArrayWithTemplate() throws Exception { - DocumentMapperParser mapperParser = createIndex("test").mapperService().documentMapperParser(); - String mapping = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("type") - .startArray("dynamic_templates").startObject().startObject("georule") - .field("match", "foo*") - .startObject("mapping").field("type", "long").endObject() - .endObject().endObject().endArray().endObject().endObject()); - DocumentMapper mapper = mapperParser.parse("type", new CompressedXContent(mapping)); + DocumentMapper mapper = createDocumentMapper(topMapping(b -> { + b.startArray("dynamic_templates"); + { + b.startObject(); + { + b.startObject("georule"); + { + b.field("match", "foo*"); + b.startObject("mapping").field("type", "long").endObject(); + } + b.endObject(); + } + b.endObject(); + } + b.endArray(); + })); - BytesReference bytes = BytesReference.bytes(XContentFactory.jsonBuilder() - .startObject().startArray("foo") - .value(0) - .value(1) - .endArray().endObject()); - ParsedDocument doc = mapper.parse(new SourceToParse("test", "type", "1", bytes, XContentType.JSON)); + ParsedDocument doc = mapper.parse(source(b -> b.startArray("foo").value(0).value(1).endArray())); assertEquals(4, doc.rootDoc().getFields("foo").length); } public void testDynamicLongArray() throws Exception { - DocumentMapperParser mapperParser = createIndex("test").mapperService().documentMapperParser(); - String mapping = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("type") - .endObject().endObject()); - DocumentMapper mapper = mapperParser.parse("type", new CompressedXContent(mapping)); - - BytesReference bytes = BytesReference.bytes(XContentFactory.jsonBuilder() - .startObject().startArray("foo") - .value(0) - .value(1) - .endArray().endObject()); - ParsedDocument doc = mapper.parse(new SourceToParse("test", "type", "1", bytes, XContentType.JSON)); + DocumentMapper mapper = createDocumentMapper(mapping(b -> {})); + ParsedDocument doc = mapper.parse(source(b -> b.startArray("foo").value(0).value(1).endArray())); assertEquals(4, doc.rootDoc().getFields("foo").length); } public void testDynamicFalseLongArray() throws Exception { - DocumentMapperParser mapperParser = createIndex("test").mapperService().documentMapperParser(); - String mapping = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("type") - .field("dynamic", "false") - .endObject().endObject()); - DocumentMapper mapper = mapperParser.parse("type", new CompressedXContent(mapping)); - - BytesReference bytes = BytesReference.bytes(XContentFactory.jsonBuilder() - .startObject().startArray("foo") - .value(0) - .value(1) - .endArray().endObject()); - ParsedDocument doc = mapper.parse(new SourceToParse("test", "type", "1", bytes, XContentType.JSON)); + DocumentMapper mapper = createDocumentMapper(topMapping(b -> b.field("dynamic", "false"))); + ParsedDocument doc = mapper.parse(source(b -> b.startArray("foo").value(0).value(1).endArray())); assertEquals(0, doc.rootDoc().getFields("foo").length); } public void testDynamicStrictLongArray() throws Exception { - DocumentMapperParser mapperParser = createIndex("test").mapperService().documentMapperParser(); - String mapping = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("type") - .field("dynamic", "strict") - .endObject().endObject()); - DocumentMapper mapper = mapperParser.parse("type", new CompressedXContent(mapping)); - - BytesReference bytes = BytesReference.bytes(XContentFactory.jsonBuilder() - .startObject().startArray("foo") - .value(0) - .value(1) - .endArray().endObject()); + DocumentMapper mapper = createDocumentMapper(topMapping(b -> b.field("dynamic", "strict"))); StrictDynamicMappingException exception = expectThrows(StrictDynamicMappingException.class, - () -> mapper.parse(new SourceToParse("test", "type", "1", bytes, XContentType.JSON))); - assertEquals("mapping set to strict, dynamic introduction of [foo] within [type] is not allowed", exception.getMessage()); + () -> mapper.parse(source(b -> b.startArray("foo").value(0).value(1).endArray()))); + assertEquals("mapping set to strict, dynamic introduction of [foo] within [_doc] is not allowed", exception.getMessage()); } public void testMappedGeoPointArray() throws Exception { - DocumentMapperParser mapperParser = createIndex("test").mapperService().documentMapperParser(); - String mapping = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("type") - .startObject("properties").startObject("foo").field("type", "geo_point") - .field("doc_values", false) - .endObject().endObject().endObject().endObject()); - DocumentMapper mapper = mapperParser.parse("type", new CompressedXContent(mapping)); - - BytesReference bytes = BytesReference.bytes(XContentFactory.jsonBuilder() - .startObject().startArray("foo") - .startArray().value(0).value(0).endArray() - .startArray().value(1).value(1).endArray() - .endArray().endObject()); - ParsedDocument doc = mapper.parse(new SourceToParse("test", "type", "1", bytes, XContentType.JSON)); - assertEquals(2, doc.rootDoc().getFields("foo").length); + DocumentMapper mapper = createDocumentMapper(fieldMapping(b -> { + b.field("type", "geo_point"); + b.field("doc_values", false); + })); + ParsedDocument doc = mapper.parse(source(b -> { + b.startArray("field"); + { + b.startArray().value(0).value(0).endArray(); + b.startArray().value(1).value(1).endArray(); + } + b.endArray(); + })); + assertEquals(2, doc.rootDoc().getFields("field").length); } public void testMappedLongArray() throws Exception { - DocumentMapperParser mapperParser = createIndex("test").mapperService().documentMapperParser(); - String mapping = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("type") - .startObject("properties").startObject("foo").field("type", "long") - .endObject().endObject().endObject().endObject()); - DocumentMapper mapper = mapperParser.parse("type", new CompressedXContent(mapping)); - - BytesReference bytes = BytesReference.bytes(XContentFactory.jsonBuilder() - .startObject().startArray("foo") - .value(0) - .value(1) - .endArray().endObject()); - ParsedDocument doc = mapper.parse(new SourceToParse("test", "type", "1", bytes, XContentType.JSON)); - assertEquals(4, doc.rootDoc().getFields("foo").length); + DocumentMapper mapper = createDocumentMapper(fieldMapping(b -> b.field("type", "long"))); + ParsedDocument doc = mapper.parse(source(b -> b.startArray("field").value(0).value(1).endArray())); + assertEquals(4, doc.rootDoc().getFields("field").length); } public void testDynamicObjectWithTemplate() throws Exception { - DocumentMapperParser mapperParser = createIndex("test").mapperService().documentMapperParser(); - String mapping = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("type") - .startArray("dynamic_templates").startObject().startObject("georule") - .field("match", "foo*") - .startObject("mapping").field("type", "object") - .startObject("properties").startObject("bar").field("type", "keyword").endObject().endObject().endObject() - .endObject().endObject().endArray().endObject().endObject()); - DocumentMapper mapper = mapperParser.parse("type", new CompressedXContent(mapping)); + DocumentMapper mapper = createDocumentMapper(topMapping(b -> { + b.startArray("dynamic_templates"); + { + b.startObject(); + { + b.startObject("georule"); + { + b.field("match", "foo*"); + b.startObject("mapping"); + { + b.field("type", "object"); + b.startObject("properties"); + { + b.startObject("bar").field("type", "keyword").endObject(); + } + b.endObject(); + } + b.endObject(); + } + b.endObject(); + } + b.endObject(); + } + b.endArray(); + })); - BytesReference bytes = BytesReference.bytes(XContentFactory.jsonBuilder() - .startObject().startObject("foo") - .field("bar", "baz") - .endObject().endObject()); - ParsedDocument doc = mapper.parse(new SourceToParse("test", "type", "1", bytes, XContentType.JSON)); + ParsedDocument doc = mapper.parse(source(b -> b.startObject("foo").field("bar", "baz").endObject())); assertEquals(2, doc.rootDoc().getFields("foo.bar").length); } public void testDynamicFalseObject() throws Exception { - DocumentMapperParser mapperParser = createIndex("test").mapperService().documentMapperParser(); - String mapping = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("type") - .field("dynamic", "false") - .endObject().endObject()); - DocumentMapper mapper = mapperParser.parse("type", new CompressedXContent(mapping)); - - BytesReference bytes = BytesReference.bytes(XContentFactory.jsonBuilder() - .startObject().startObject("foo") - .field("bar", "baz") - .endObject().endObject()); - ParsedDocument doc = mapper.parse(new SourceToParse("test", "type", "1", bytes, XContentType.JSON)); + DocumentMapper mapper = createDocumentMapper(topMapping(b -> b.field("dynamic", "false"))); + ParsedDocument doc = mapper.parse(source(b -> b.startObject("foo").field("bar", "baz").endObject())); assertEquals(0, doc.rootDoc().getFields("foo.bar").length); } public void testDynamicStrictObject() throws Exception { - DocumentMapperParser mapperParser = createIndex("test").mapperService().documentMapperParser(); - String mapping = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("type") - .field("dynamic", "strict") - .endObject().endObject()); - DocumentMapper mapper = mapperParser.parse("type", new CompressedXContent(mapping)); - - BytesReference bytes = BytesReference.bytes(XContentFactory.jsonBuilder() - .startObject().startObject("foo") - .field("bar", "baz") - .endObject().endObject()); + DocumentMapper mapper = createDocumentMapper(topMapping(b -> b.field("dynamic", "strict"))); StrictDynamicMappingException exception = expectThrows(StrictDynamicMappingException.class, - () -> mapper.parse(new SourceToParse("test", "type", "1", bytes, XContentType.JSON))); - assertEquals("mapping set to strict, dynamic introduction of [foo] within [type] is not allowed", exception.getMessage()); + () -> mapper.parse(source(b -> b.startObject("foo").field("bar", "baz").endObject()))); + assertEquals("mapping set to strict, dynamic introduction of [foo] within [_doc] is not allowed", exception.getMessage()); } public void testDynamicFalseValue() throws Exception { - DocumentMapperParser mapperParser = createIndex("test").mapperService().documentMapperParser(); - String mapping = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("type") - .field("dynamic", "false") - .endObject().endObject()); - DocumentMapper mapper = mapperParser.parse("type", new CompressedXContent(mapping)); - - BytesReference bytes = BytesReference.bytes(XContentFactory.jsonBuilder() - .startObject() - .field("bar", "baz") - .endObject()); - ParsedDocument doc = mapper.parse(new SourceToParse("test", "type", "1", bytes, XContentType.JSON)); + DocumentMapper mapper = createDocumentMapper(topMapping(b -> b.field("dynamic", "false"))); + ParsedDocument doc = mapper.parse(source(b -> b.field("bar", "baz"))); assertEquals(0, doc.rootDoc().getFields("bar").length); } public void testDynamicStrictValue() throws Exception { - DocumentMapperParser mapperParser = createIndex("test").mapperService().documentMapperParser(); - String mapping = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("type") - .field("dynamic", "strict") - .endObject().endObject()); - DocumentMapper mapper = mapperParser.parse("type", new CompressedXContent(mapping)); - - BytesReference bytes = BytesReference.bytes(XContentFactory.jsonBuilder() - .startObject() - .field("bar", "baz") - .endObject()); + DocumentMapper mapper = createDocumentMapper(topMapping(b -> b.field("dynamic", "strict"))); StrictDynamicMappingException exception = expectThrows(StrictDynamicMappingException.class, - () -> mapper.parse(new SourceToParse("test", "type", "1", bytes, XContentType.JSON))); - assertEquals("mapping set to strict, dynamic introduction of [bar] within [type] is not allowed", exception.getMessage()); + () -> mapper.parse(source(b -> b.field("bar", "baz")))); + assertEquals("mapping set to strict, dynamic introduction of [bar] within [_doc] is not allowed", exception.getMessage()); } public void testDynamicFalseNull() throws Exception { - DocumentMapperParser mapperParser = createIndex("test").mapperService().documentMapperParser(); - String mapping = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("type") - .field("dynamic", "false") - .endObject().endObject()); - DocumentMapper mapper = mapperParser.parse("type", new CompressedXContent(mapping)); - - BytesReference bytes = BytesReference.bytes(XContentFactory.jsonBuilder() - .startObject() - .field("bar", (String) null) - .endObject()); - ParsedDocument doc = mapper.parse(new SourceToParse("test", "type", "1", bytes, XContentType.JSON)); + DocumentMapper mapper = createDocumentMapper(topMapping(b -> b.field("dynamic", "false"))); + ParsedDocument doc = mapper.parse(source(b -> b.nullField("bar"))); assertEquals(0, doc.rootDoc().getFields("bar").length); } public void testDynamicStrictNull() throws Exception { - DocumentMapperParser mapperParser = createIndex("test").mapperService().documentMapperParser(); - String mapping = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("type") - .field("dynamic", "strict") - .endObject().endObject()); - DocumentMapper mapper = mapperParser.parse("type", new CompressedXContent(mapping)); - - BytesReference bytes = BytesReference.bytes(XContentFactory.jsonBuilder() - .startObject() - .field("bar", (String) null) - .endObject()); + DocumentMapper mapper = createDocumentMapper(topMapping(b -> b.field("dynamic", "strict"))); StrictDynamicMappingException exception = expectThrows(StrictDynamicMappingException.class, - () -> mapper.parse(new SourceToParse("test", "type", "1", bytes, XContentType.JSON))); - assertEquals("mapping set to strict, dynamic introduction of [bar] within [type] is not allowed", exception.getMessage()); + () -> mapper.parse(source(b -> b.nullField("bar")))); + assertEquals("mapping set to strict, dynamic introduction of [bar] within [_doc] is not allowed", exception.getMessage()); } public void testMappedNullValue() throws Exception { - DocumentMapperParser mapperParser = createIndex("test").mapperService().documentMapperParser(); - String mapping = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("type") - .startObject("properties").startObject("foo").field("type", "long") - .endObject().endObject().endObject().endObject()); - DocumentMapper mapper = mapperParser.parse("type", new CompressedXContent(mapping)); - - BytesReference bytes = BytesReference.bytes(XContentFactory.jsonBuilder() - .startObject().field("foo", (Long) null) - .endObject()); - ParsedDocument doc = mapper.parse(new SourceToParse("test", "type", "1", bytes, XContentType.JSON)); + DocumentMapper mapper = createDocumentMapper(fieldMapping(b -> b.field("type", "long"))); + ParsedDocument doc = mapper.parse(source(b -> b.nullField("foo"))); assertEquals(0, doc.rootDoc().getFields("foo").length); } public void testDynamicBigInteger() throws Exception { - DocumentMapperParser mapperParser = createIndex("test").mapperService().documentMapperParser(); - String mapping = Strings.toString(XContentFactory.jsonBuilder().startObject() - .startObject("type") - .startArray("dynamic_templates").startObject() - .startObject("big-integer-to-keyword") - .field("match", "big-*") - .field("match_mapping_type", "long") - .startObject("mapping").field("type", "keyword").endObject() - .endObject() - .endObject().endArray() - .endObject() - .endObject()); - - DocumentMapper mapper = mapperParser.parse("type", new CompressedXContent(mapping)); + DocumentMapper mapper = createDocumentMapper(topMapping(b -> { + b.startArray("dynamic_templates"); + { + b.startObject(); + { + b.startObject("big-integer-to-keyword"); + { + b.field("match", "big-*"); + b.field("match_mapping_type", "long"); + b.startObject("mapping").field("type", "keyword").endObject(); + } + b.endObject(); + } + b.endObject(); + } + b.endArray(); + })); BigInteger value = BigInteger.valueOf(Long.MAX_VALUE).add(BigInteger.ONE); - BytesReference bytes = BytesReference.bytes(XContentFactory.jsonBuilder().startObject() - .field("big-integer", value) - .endObject()); - ParsedDocument doc = mapper.parse(new SourceToParse("test", "type", "1", bytes, XContentType.JSON)); + ParsedDocument doc = mapper.parse(source(b -> b.field("big-integer", value))); IndexableField[] fields = doc.rootDoc().getFields("big-integer"); assertEquals(2, fields.length); @@ -742,27 +642,26 @@ public class DocumentParserTests extends ESSingleNodeTestCase { } public void testDynamicBigDecimal() throws Exception { - DocumentMapperParser mapperParser = createIndex("test").mapperService().documentMapperParser(); - String mapping = Strings.toString(XContentFactory.jsonBuilder().startObject() - .startObject("type") - .startArray("dynamic_templates").startObject() - .startObject("big-decimal-to-scaled-float") - .field("match", "big-*") - .field("match_mapping_type", "double") - .startObject("mapping") - .field("type", "keyword") - .endObject() - .endObject() - .endObject().endArray() - .endObject() - .endObject()); + DocumentMapper mapper = createDocumentMapper(topMapping(b -> { + b.startArray("dynamic_templates"); + { + b.startObject(); + { + b.startObject("big-decimal-to-scaled-float"); + { + b.field("match", "big-*"); + b.field("match_mapping_type", "double"); + b.startObject("mapping").field("type", "keyword").endObject(); + } + b.endObject(); + } + b.endObject(); + } + b.endArray(); + })); BigDecimal value = BigDecimal.valueOf(Double.MAX_VALUE).add(BigDecimal.valueOf(10.1)); - DocumentMapper mapper = mapperParser.parse("type", new CompressedXContent(mapping)); - BytesReference bytes = BytesReference.bytes(XContentFactory.jsonBuilder().startObject() - .field("big-decimal", value) - .endObject()); - ParsedDocument doc = mapper.parse(new SourceToParse("test", "type", "1", bytes, XContentType.JSON)); + ParsedDocument doc = mapper.parse(source(b -> b.field("big-decimal", value))); IndexableField[] fields = doc.rootDoc().getFields("big-decimal"); assertEquals(2, fields.length); @@ -770,17 +669,9 @@ public class DocumentParserTests extends ESSingleNodeTestCase { } public void testDynamicDottedFieldNameLongArray() throws Exception { - DocumentMapperParser mapperParser = createIndex("test").mapperService().documentMapperParser(); - String mapping = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("type") - .endObject().endObject()); - DocumentMapper mapper = mapperParser.parse("type", new CompressedXContent(mapping)); + DocumentMapper mapper = createDocumentMapper(mapping(b -> {})); - BytesReference bytes = BytesReference.bytes(XContentFactory.jsonBuilder() - .startObject().startArray("foo.bar.baz") - .value(0) - .value(1) - .endArray().endObject()); - ParsedDocument doc = mapper.parse(new SourceToParse("test", "type", "1", bytes, XContentType.JSON)); + ParsedDocument doc = mapper.parse(source(b -> b.startArray("foo.bar.baz").value(0).value(1).endArray())); assertEquals(4, doc.rootDoc().getFields("foo.bar.baz").length); Mapper fooMapper = doc.dynamicMappingsUpdate().root().getMapper("foo"); assertNotNull(fooMapper); @@ -794,20 +685,24 @@ public class DocumentParserTests extends ESSingleNodeTestCase { } public void testDynamicDottedFieldNameLongArrayWithParentTemplate() throws Exception { - DocumentMapperParser mapperParser = createIndex("test").mapperService().documentMapperParser(); - String mapping = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("type") - .startArray("dynamic_templates").startObject().startObject("georule") - .field("match", "foo*") - .startObject("mapping").field("type", "object").endObject() - .endObject().endObject().endArray().endObject().endObject()); - DocumentMapper mapper = mapperParser.parse("type", new CompressedXContent(mapping)); + DocumentMapper mapper = createDocumentMapper(topMapping(b -> { + b.startArray("dynamic_templates"); + { + b.startObject(); + { + b.startObject("georule"); + { + b.field("match", "foo*"); + b.startObject("mapping").field("type", "object").endObject(); + } + b.endObject(); + } + b.endObject(); + } + b.endArray(); + })); - BytesReference bytes = BytesReference.bytes(XContentFactory.jsonBuilder() - .startObject().startArray("foo.bar.baz") - .value(0) - .value(1) - .endArray().endObject()); - ParsedDocument doc = mapper.parse(new SourceToParse("test", "type", "1", bytes, XContentType.JSON)); + ParsedDocument doc = mapper.parse(source(b -> b.startArray("foo.bar.baz").value(0).value(1).endArray())); assertEquals(4, doc.rootDoc().getFields("foo.bar.baz").length); Mapper fooMapper = doc.dynamicMappingsUpdate().root().getMapper("foo"); assertNotNull(fooMapper); @@ -821,21 +716,11 @@ public class DocumentParserTests extends ESSingleNodeTestCase { } public void testDynamicDottedFieldNameLongArrayWithExistingParent() throws Exception { - DocumentMapperParser mapperParser = createIndex("test").mapperService().documentMapperParser(); - String mapping = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("type") - .startObject("properties") .startObject("foo") - .field("type", "object") - .endObject().endObject().endObject().endObject()); - DocumentMapper mapper = mapperParser.parse("type", new CompressedXContent(mapping)); + DocumentMapper mapper = createDocumentMapper(fieldMapping(b -> b.field("type", "object"))); + ParsedDocument doc = mapper.parse(source(b -> b.startArray("field.bar.baz").value(0).value(1).endArray())); - BytesReference bytes = BytesReference.bytes(XContentFactory.jsonBuilder() - .startObject().startArray("foo.bar.baz") - .value(0) - .value(1) - .endArray().endObject()); - ParsedDocument doc = mapper.parse(new SourceToParse("test", "type", "1", bytes, XContentType.JSON)); - assertEquals(4, doc.rootDoc().getFields("foo.bar.baz").length); - Mapper fooMapper = doc.dynamicMappingsUpdate().root().getMapper("foo"); + assertEquals(4, doc.rootDoc().getFields("field.bar.baz").length); + Mapper fooMapper = doc.dynamicMappingsUpdate().root().getMapper("field"); assertNotNull(fooMapper); assertThat(fooMapper, instanceOf(ObjectMapper.class)); Mapper barMapper = ((ObjectMapper) fooMapper).getMapper("bar"); @@ -847,67 +732,29 @@ public class DocumentParserTests extends ESSingleNodeTestCase { } public void testDynamicDottedFieldNameLongArrayWithExistingParentWrongType() throws Exception { - DocumentMapperParser mapperParser = createIndex("test").mapperService().documentMapperParser(); - String mapping = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("type") - .startObject("properties") .startObject("foo") - .field("type", "long") - .endObject().endObject().endObject().endObject()); - DocumentMapper mapper = mapperParser.parse("type", new CompressedXContent(mapping)); - - BytesReference bytes = BytesReference.bytes(XContentFactory.jsonBuilder() - .startObject().startArray("foo.bar.baz") - .value(0) - .value(1) - .endArray().endObject()); + DocumentMapper mapper = createDocumentMapper(fieldMapping(b -> b.field("type", "long"))); MapperParsingException exception = expectThrows(MapperParsingException.class, - () -> mapper.parse(new SourceToParse("test", "type", "1", bytes, XContentType.JSON))); - assertEquals("Could not dynamically add mapping for field [foo.bar.baz]. " - + "Existing mapping for [foo] must be of type object but found [long].", exception.getMessage()); + () -> mapper.parse(source(b -> b.startArray("field.bar.baz").value(0).value(1).endArray()))); + assertEquals("Could not dynamically add mapping for field [field.bar.baz]. " + + "Existing mapping for [field] must be of type object but found [long].", exception.getMessage()); } public void testDynamicFalseDottedFieldNameLongArray() throws Exception { - DocumentMapperParser mapperParser = createIndex("test").mapperService().documentMapperParser(); - String mapping = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("type") - .field("dynamic", "false") - .endObject().endObject()); - DocumentMapper mapper = mapperParser.parse("type", new CompressedXContent(mapping)); - - BytesReference bytes = BytesReference.bytes(XContentFactory.jsonBuilder() - .startObject().startArray("foo.bar.baz") - .value(0) - .value(1) - .endArray().endObject()); - ParsedDocument doc = mapper.parse(new SourceToParse("test", "type", "1", bytes, XContentType.JSON)); + DocumentMapper mapper = createDocumentMapper(topMapping(b -> b.field("dynamic", "false"))); + ParsedDocument doc = mapper.parse(source(b -> b.startArray("foo.bar.baz").value(0).value(1).endArray())); assertEquals(0, doc.rootDoc().getFields("foo.bar.baz").length); } public void testDynamicStrictDottedFieldNameLongArray() throws Exception { - DocumentMapperParser mapperParser = createIndex("test").mapperService().documentMapperParser(); - String mapping = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("type") - .field("dynamic", "strict") - .endObject().endObject()); - DocumentMapper mapper = mapperParser.parse("type", new CompressedXContent(mapping)); - - BytesReference bytes = BytesReference.bytes(XContentFactory.jsonBuilder() - .startObject().startArray("foo.bar.baz") - .value(0) - .value(1) - .endArray().endObject()); + DocumentMapper mapper = createDocumentMapper(topMapping(b -> b.field("dynamic", "strict"))); StrictDynamicMappingException exception = expectThrows(StrictDynamicMappingException.class, - () -> mapper.parse(new SourceToParse("test", "type", "1", bytes, XContentType.JSON))); - assertEquals("mapping set to strict, dynamic introduction of [foo] within [type] is not allowed", exception.getMessage()); + () -> mapper.parse(source(b -> b.startArray("foo.bar.baz").value(0).value(1).endArray()))); + assertEquals("mapping set to strict, dynamic introduction of [foo] within [_doc] is not allowed", exception.getMessage()); } public void testDynamicDottedFieldNameLong() throws Exception { - DocumentMapperParser mapperParser = createIndex("test").mapperService().documentMapperParser(); - String mapping = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("type") - .endObject().endObject()); - DocumentMapper mapper = mapperParser.parse("type", new CompressedXContent(mapping)); - - BytesReference bytes = BytesReference.bytes(XContentFactory.jsonBuilder() - .startObject().field("foo.bar.baz", 0) - .endObject()); - ParsedDocument doc = mapper.parse(new SourceToParse("test", "type", "1", bytes, XContentType.JSON)); + DocumentMapper mapper = createDocumentMapper(mapping(b -> {})); + ParsedDocument doc = mapper.parse(source(b -> b.field("foo.bar.baz", 0))); assertEquals(2, doc.rootDoc().getFields("foo.bar.baz").length); Mapper fooMapper = doc.dynamicMappingsUpdate().root().getMapper("foo"); assertNotNull(fooMapper); @@ -921,18 +768,24 @@ public class DocumentParserTests extends ESSingleNodeTestCase { } public void testDynamicDottedFieldNameLongWithParentTemplate() throws Exception { - DocumentMapperParser mapperParser = createIndex("test").mapperService().documentMapperParser(); - String mapping = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("type") - .startArray("dynamic_templates").startObject().startObject("georule") - .field("match", "foo*") - .startObject("mapping").field("type", "object").endObject() - .endObject().endObject().endArray().endObject().endObject()); - DocumentMapper mapper = mapperParser.parse("type", new CompressedXContent(mapping)); + DocumentMapper mapper = createDocumentMapper(topMapping(b -> { + b.startArray("dynamic_templates"); + { + b.startObject(); + { + b.startObject("georule"); + { + b.field("match", "foo*"); + b.startObject("mapping").field("type", "object").endObject(); + } + b.endObject(); + } + b.endObject(); + } + b.endArray(); + })); - BytesReference bytes = BytesReference.bytes(XContentFactory.jsonBuilder() - .startObject().field("foo.bar.baz", 0) - .endObject()); - ParsedDocument doc = mapper.parse(new SourceToParse("test", "type", "1", bytes, XContentType.JSON)); + ParsedDocument doc = mapper.parse(source(b -> b.field("foo.bar.baz", 0))); assertEquals(2, doc.rootDoc().getFields("foo.bar.baz").length); Mapper fooMapper = doc.dynamicMappingsUpdate().root().getMapper("foo"); assertNotNull(fooMapper); @@ -946,19 +799,10 @@ public class DocumentParserTests extends ESSingleNodeTestCase { } public void testDynamicDottedFieldNameLongWithExistingParent() throws Exception { - DocumentMapperParser mapperParser = createIndex("test").mapperService().documentMapperParser(); - String mapping = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("type") - .startObject("properties") .startObject("foo") - .field("type", "object") - .endObject().endObject().endObject().endObject()); - DocumentMapper mapper = mapperParser.parse("type", new CompressedXContent(mapping)); - - BytesReference bytes = BytesReference.bytes(XContentFactory.jsonBuilder() - .startObject().field("foo.bar.baz", 0) - .endObject()); - ParsedDocument doc = mapper.parse(new SourceToParse("test", "type", "1", bytes, XContentType.JSON)); - assertEquals(2, doc.rootDoc().getFields("foo.bar.baz").length); - Mapper fooMapper = doc.dynamicMappingsUpdate().root().getMapper("foo"); + DocumentMapper mapper = createDocumentMapper(fieldMapping(b -> b.field("type", "object"))); + ParsedDocument doc = mapper.parse(source(b -> b.field("field.bar.baz", 0))); + assertEquals(2, doc.rootDoc().getFields("field.bar.baz").length); + Mapper fooMapper = doc.dynamicMappingsUpdate().root().getMapper("field"); assertNotNull(fooMapper); assertThat(fooMapper, instanceOf(ObjectMapper.class)); Mapper barMapper = ((ObjectMapper) fooMapper).getMapper("bar"); @@ -970,62 +814,29 @@ public class DocumentParserTests extends ESSingleNodeTestCase { } public void testDynamicDottedFieldNameLongWithExistingParentWrongType() throws Exception { - DocumentMapperParser mapperParser = createIndex("test").mapperService().documentMapperParser(); - String mapping = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("type") - .startObject("properties") .startObject("foo") - .field("type", "long") - .endObject().endObject().endObject().endObject()); - DocumentMapper mapper = mapperParser.parse("type", new CompressedXContent(mapping)); - - BytesReference bytes = BytesReference.bytes(XContentFactory.jsonBuilder() - .startObject().field("foo.bar.baz", 0) - .endObject()); + DocumentMapper mapper = createDocumentMapper(fieldMapping(b -> b.field("type", "long"))); MapperParsingException exception = expectThrows(MapperParsingException.class, - () -> mapper.parse(new SourceToParse("test", "type", "1", bytes, XContentType.JSON))); - assertEquals("Could not dynamically add mapping for field [foo.bar.baz]. " - + "Existing mapping for [foo] must be of type object but found [long].", exception.getMessage()); + () -> mapper.parse(source(b -> b.field("field.bar.baz", 0)))); + assertEquals("Could not dynamically add mapping for field [field.bar.baz]. " + + "Existing mapping for [field] must be of type object but found [long].", exception.getMessage()); } public void testDynamicFalseDottedFieldNameLong() throws Exception { - DocumentMapperParser mapperParser = createIndex("test").mapperService().documentMapperParser(); - String mapping = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("type") - .field("dynamic", "false") - .endObject().endObject()); - DocumentMapper mapper = mapperParser.parse("type", new CompressedXContent(mapping)); - - BytesReference bytes = BytesReference.bytes(XContentFactory.jsonBuilder() - .startObject().field("foo.bar.baz", 0) - .endObject()); - ParsedDocument doc = mapper.parse(new SourceToParse("test", "type", "1", bytes, XContentType.JSON)); + DocumentMapper mapper = createDocumentMapper(topMapping(b -> b.field("dynamic", "false"))); + ParsedDocument doc = mapper.parse(source(b -> b.field("foo.bar.baz", 0))); assertEquals(0, doc.rootDoc().getFields("foo.bar.baz").length); } public void testDynamicStrictDottedFieldNameLong() throws Exception { - DocumentMapperParser mapperParser = createIndex("test").mapperService().documentMapperParser(); - String mapping = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("type") - .field("dynamic", "strict") - .endObject().endObject()); - DocumentMapper mapper = mapperParser.parse("type", new CompressedXContent(mapping)); - - BytesReference bytes = BytesReference.bytes(XContentFactory.jsonBuilder() - .startObject().field("foo.bar.baz", 0) - .endObject()); + DocumentMapper mapper = createDocumentMapper(topMapping(b -> b.field("dynamic", "strict"))); StrictDynamicMappingException exception = expectThrows(StrictDynamicMappingException.class, - () -> mapper.parse(new SourceToParse("test", "type", "1", bytes, XContentType.JSON))); - assertEquals("mapping set to strict, dynamic introduction of [foo] within [type] is not allowed", exception.getMessage()); + () -> mapper.parse(source(b -> b.field("foo.bar.baz", 0)))); + assertEquals("mapping set to strict, dynamic introduction of [foo] within [_doc] is not allowed", exception.getMessage()); } public void testDynamicDottedFieldNameObject() throws Exception { - DocumentMapperParser mapperParser = createIndex("test").mapperService().documentMapperParser(); - String mapping = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("type") - .endObject().endObject()); - DocumentMapper mapper = mapperParser.parse("type", new CompressedXContent(mapping)); - - BytesReference bytes = BytesReference.bytes(XContentFactory.jsonBuilder() - .startObject().startObject("foo.bar.baz") - .field("a", 0) - .endObject().endObject()); - ParsedDocument doc = mapper.parse(new SourceToParse("test", "type", "1", bytes, XContentType.JSON)); + DocumentMapper mapper = createDocumentMapper(mapping(b -> {})); + ParsedDocument doc = mapper.parse(source(b -> b.startObject("foo.bar.baz").field("a", 0).endObject())); assertEquals(2, doc.rootDoc().getFields("foo.bar.baz.a").length); Mapper fooMapper = doc.dynamicMappingsUpdate().root().getMapper("foo"); assertNotNull(fooMapper); @@ -1042,19 +853,25 @@ public class DocumentParserTests extends ESSingleNodeTestCase { } public void testDynamicDottedFieldNameObjectWithParentTemplate() throws Exception { - DocumentMapperParser mapperParser = createIndex("test").mapperService().documentMapperParser(); - String mapping = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("type") - .startArray("dynamic_templates").startObject().startObject("georule") - .field("match", "foo*") - .startObject("mapping").field("type", "object").endObject() - .endObject().endObject().endArray().endObject().endObject()); - DocumentMapper mapper = mapperParser.parse("type", new CompressedXContent(mapping)); + DocumentMapper mapper = createDocumentMapper(topMapping(b -> { + b.startArray("dynamic_templates"); + { + b.startObject(); + { + b.startObject("georule"); + { + b.field("match", "foo*"); + b.startObject("mapping").field("type", "object").endObject(); + } + b.endObject(); + } + b.endObject(); + } + b.endArray(); + })); + + ParsedDocument doc = mapper.parse(source(b -> b.startObject("foo.bar.baz").field("a", 0).endObject())); - BytesReference bytes = BytesReference.bytes(XContentFactory.jsonBuilder() - .startObject().startObject("foo.bar.baz") - .field("a", 0) - .endObject().endObject()); - ParsedDocument doc = mapper.parse(new SourceToParse("test", "type", "1", bytes, XContentType.JSON)); assertEquals(2, doc.rootDoc().getFields("foo.bar.baz.a").length); Mapper fooMapper = doc.dynamicMappingsUpdate().root().getMapper("foo"); assertNotNull(fooMapper); @@ -1071,16 +888,10 @@ public class DocumentParserTests extends ESSingleNodeTestCase { } public void testDynamicDottedFieldNameObjectWithExistingParent() throws Exception { - DocumentMapperParser mapperParser = createIndex("test").mapperService().documentMapperParser(); - String mapping = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("type").startObject("properties") - .startObject("foo").field("type", "object").endObject().endObject().endObject().endObject()); - DocumentMapper mapper = mapperParser.parse("type", new CompressedXContent(mapping)); - - BytesReference bytes = BytesReference.bytes(XContentFactory.jsonBuilder().startObject().startObject("foo.bar.baz") - .field("a", 0).endObject().endObject()); - ParsedDocument doc = mapper.parse(new SourceToParse("test", "type", "1", bytes, XContentType.JSON)); - assertEquals(2, doc.rootDoc().getFields("foo.bar.baz.a").length); - Mapper fooMapper = doc.dynamicMappingsUpdate().root().getMapper("foo"); + DocumentMapper mapper = createDocumentMapper(fieldMapping(b -> b.field("type", "object"))); + ParsedDocument doc = mapper.parse(source(b -> b.startObject("field.bar.baz").field("a", 0).endObject())); + assertEquals(2, doc.rootDoc().getFields("field.bar.baz.a").length); + Mapper fooMapper = doc.dynamicMappingsUpdate().root().getMapper("field"); assertNotNull(fooMapper); assertThat(fooMapper, instanceOf(ObjectMapper.class)); Mapper barMapper = ((ObjectMapper) fooMapper).getMapper("bar"); @@ -1095,183 +906,149 @@ public class DocumentParserTests extends ESSingleNodeTestCase { } public void testDynamicDottedFieldNameObjectWithExistingParentWrongType() throws Exception { - DocumentMapperParser mapperParser = createIndex("test").mapperService().documentMapperParser(); - String mapping = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("type") - .startObject("properties") .startObject("foo") - .field("type", "long") - .endObject().endObject().endObject().endObject()); - DocumentMapper mapper = mapperParser.parse("type", new CompressedXContent(mapping)); - - BytesReference bytes = BytesReference.bytes(XContentFactory.jsonBuilder().startObject().startObject("foo.bar.baz") - .field("a", 0).endObject().endObject()); + DocumentMapper mapper = createDocumentMapper(fieldMapping(b -> b.field("type", "long"))); MapperParsingException exception = expectThrows(MapperParsingException.class, - () -> mapper.parse(new SourceToParse("test", "type", "1", bytes, XContentType.JSON))); - - assertEquals("Could not dynamically add mapping for field [foo.bar.baz]. " - + "Existing mapping for [foo] must be of type object but found [long].", exception.getMessage()); + () -> mapper.parse(source(b -> b.startObject("field.bar.baz").field("a", 0).endObject()))); + assertEquals("Could not dynamically add mapping for field [field.bar.baz]. " + + "Existing mapping for [field] must be of type object but found [long].", exception.getMessage()); } public void testDynamicFalseDottedFieldNameObject() throws Exception { - DocumentMapperParser mapperParser = createIndex("test").mapperService().documentMapperParser(); - String mapping = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("type") - .field("dynamic", "false") - .endObject().endObject()); - DocumentMapper mapper = mapperParser.parse("type", new CompressedXContent(mapping)); - - BytesReference bytes = BytesReference.bytes(XContentFactory.jsonBuilder() - .startObject().startObject("foo.bar.baz") - .field("a", 0) - .endObject().endObject()); - ParsedDocument doc = mapper.parse(new SourceToParse("test", "type", "1", bytes, XContentType.JSON)); + DocumentMapper mapper = createDocumentMapper(topMapping(b -> b.field("dynamic", "false"))); + ParsedDocument doc = mapper.parse(source(b -> b.startObject("foo.bar.baz").field("a", 0).endObject())); assertEquals(0, doc.rootDoc().getFields("foo.bar.baz.a").length); } public void testDynamicStrictDottedFieldNameObject() throws Exception { - DocumentMapperParser mapperParser = createIndex("test").mapperService().documentMapperParser(); - String mapping = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("type") - .field("dynamic", "strict") - .endObject().endObject()); - DocumentMapper mapper = mapperParser.parse("type", new CompressedXContent(mapping)); - - BytesReference bytes = BytesReference.bytes(XContentFactory.jsonBuilder() - .startObject().startObject("foo.bar.baz") - .field("a", 0) - .endObject().endObject()); + DocumentMapper mapper = createDocumentMapper(topMapping(b -> b.field("dynamic", "strict"))); StrictDynamicMappingException exception = expectThrows(StrictDynamicMappingException.class, - () -> mapper.parse(new SourceToParse("test", "type", "1", bytes, XContentType.JSON))); - assertEquals("mapping set to strict, dynamic introduction of [foo] within [type] is not allowed", exception.getMessage()); + () -> mapper.parse(source(b -> b.startObject("foo.bar.baz").field("a", 0).endObject()))); + assertEquals("mapping set to strict, dynamic introduction of [foo] within [_doc] is not allowed", exception.getMessage()); } public void testDocumentContainsMetadataField() throws Exception { - DocumentMapperParser mapperParser = createIndex("test").mapperService().documentMapperParser(); - String mapping = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("_doc").endObject().endObject()); - DocumentMapper mapper = mapperParser.parse("_doc", new CompressedXContent(mapping)); - - BytesReference bytes = BytesReference.bytes(XContentFactory.jsonBuilder().startObject().field("_field_names", 0).endObject()); + DocumentMapper mapper = createDocumentMapper(mapping(b -> {})); MapperParsingException e = expectThrows(MapperParsingException.class, () -> - mapper.parse(new SourceToParse("test", "_doc", "1", bytes, XContentType.JSON))); + mapper.parse(source(b -> b.field("_field_names", 0)))); assertTrue(e.getMessage(), e.getMessage().contains("Field [_field_names] is a metadata field and cannot be added inside a document.")); - BytesReference bytes2 = BytesReference.bytes(XContentFactory.jsonBuilder().startObject() - .field("foo._field_names", 0).endObject()); - mapper.parse(new SourceToParse("test", "_doc", "1", bytes2, XContentType.JSON)); // parses without error + mapper.parse(source(b -> b.field("foo._field_names", 0))); // parses without error } public void testSimpleMapper() throws Exception { - IndexService indexService = createIndex("test"); - DocumentMapper docMapper = new DocumentMapper.Builder( - new RootObjectMapper.Builder("person") - .add(new ObjectMapper.Builder("name") - .add(new TextFieldMapper.Builder("first").store(true).index(false))), - indexService.mapperService()).build(indexService.mapperService()); + DocumentMapper docMapper = createDocumentMapper(mapping(b -> { + b.startObject("name"); + { + b.field("type", "object"); + b.startObject("properties"); + { + b.startObject("first"); + { + b.field("type", "text"); + b.field("store", "true"); + b.field("index", false); + } + b.endObject(); + } + b.endObject(); + } + b.endObject(); + })); - BytesReference json = new BytesArray(copyToBytesFromClasspath("/org/elasticsearch/index/mapper/simple/test1.json")); - Document doc = docMapper.parse(new SourceToParse("test", "person", "1", json, XContentType.JSON)).rootDoc(); + Document doc = docMapper.parse(source(b -> { + b.startObject("name"); + { + b.field("first", "shay"); + b.field("last", "banon"); + } + b.endObject(); + })).rootDoc(); assertThat(doc.get(docMapper.mappers().getMapper("name.first").name()), equalTo("shay")); - doc = docMapper.parse(new SourceToParse("test", "person", "1", json, XContentType.JSON)).rootDoc(); } public void testParseToJsonAndParse() throws Exception { String mapping = copyToStringFromClasspath("/org/elasticsearch/index/mapper/simple/test-mapping.json"); - DocumentMapperParser parser = createIndex("test").mapperService().documentMapperParser(); - DocumentMapper docMapper = parser.parse("person", new CompressedXContent(mapping)); - String builtMapping = docMapper.mappingSource().string(); + MapperService mapperService = createMapperService(mapping(b -> {})); + merge("person", mapperService, mapping); + String builtMapping = mapperService.documentMapper().mappingSource().string(); // reparse it - DocumentMapper builtDocMapper = parser.parse("person", new CompressedXContent(builtMapping)); + DocumentMapper builtDocMapper = createDocumentMapper("_doc", builtMapping); BytesReference json = new BytesArray(copyToBytesFromClasspath("/org/elasticsearch/index/mapper/simple/test1.json")); - Document doc = builtDocMapper.parse(new SourceToParse("test", "person", "1", json, XContentType.JSON)).rootDoc(); - assertThat(doc.getBinaryValue(docMapper.idFieldMapper().name()), equalTo(Uid.encodeId("1"))); - assertThat(doc.get(docMapper.mappers().getMapper("name.first").name()), equalTo("shay")); + Document doc = builtDocMapper.parse(new SourceToParse("test", "_doc", "1", json, XContentType.JSON)).rootDoc(); + assertThat(doc.getBinaryValue(builtDocMapper.idFieldMapper().name()), equalTo(Uid.encodeId("1"))); + assertThat(doc.get(builtDocMapper.mappers().getMapper("name.first").name()), equalTo("shay")); } public void testSimpleParser() throws Exception { String mapping = copyToStringFromClasspath("/org/elasticsearch/index/mapper/simple/test-mapping.json"); - DocumentMapper docMapper = createIndex("test").mapperService().documentMapperParser() - .parse("person", new CompressedXContent(mapping)); + DocumentMapper docMapper = createDocumentMapper("person", mapping); assertThat((String) docMapper.meta().get("param1"), equalTo("value1")); BytesReference json = new BytesArray(copyToBytesFromClasspath("/org/elasticsearch/index/mapper/simple/test1.json")); - Document doc = docMapper.parse(new SourceToParse("test", "person", "1", json, XContentType.JSON)).rootDoc(); + Document doc = docMapper.parse(new SourceToParse("test", "_doc", "1", json, XContentType.JSON)).rootDoc(); assertThat(doc.getBinaryValue(docMapper.idFieldMapper().name()), equalTo(Uid.encodeId("1"))); assertThat(doc.get(docMapper.mappers().getMapper("name.first").name()), equalTo("shay")); } public void testSimpleParserNoTypeNoId() throws Exception { String mapping = copyToStringFromClasspath("/org/elasticsearch/index/mapper/simple/test-mapping.json"); - DocumentMapper docMapper = createIndex("test").mapperService().documentMapperParser() - .parse("person", new CompressedXContent(mapping)); + DocumentMapper docMapper = createDocumentMapper("person", mapping); BytesReference json = new BytesArray(copyToBytesFromClasspath("/org/elasticsearch/index/mapper/simple/test1-notype-noid.json")); - Document doc = docMapper.parse(new SourceToParse("test", "person", "1", json, XContentType.JSON)).rootDoc(); + Document doc = docMapper.parse(new SourceToParse("test", "_doc", "1", json, XContentType.JSON)).rootDoc(); assertThat(doc.getBinaryValue(docMapper.idFieldMapper().name()), equalTo(Uid.encodeId("1"))); assertThat(doc.get(docMapper.mappers().getMapper("name.first").name()), equalTo("shay")); } public void testAttributes() throws Exception { String mapping = copyToStringFromClasspath("/org/elasticsearch/index/mapper/simple/test-mapping.json"); - DocumentMapperParser parser = createIndex("test").mapperService().documentMapperParser(); - DocumentMapper docMapper = parser.parse("person", new CompressedXContent(mapping)); + + DocumentMapper docMapper = createDocumentMapper("person", mapping); assertThat((String) docMapper.meta().get("param1"), equalTo("value1")); String builtMapping = docMapper.mappingSource().string(); - DocumentMapper builtDocMapper = parser.parse("person", new CompressedXContent(builtMapping)); + DocumentMapper builtDocMapper = createDocumentMapper("_doc", builtMapping); assertThat((String) builtDocMapper.meta().get("param1"), equalTo("value1")); } public void testNoDocumentSent() throws Exception { - IndexService indexService = createIndex("test"); - DocumentMapper docMapper = new DocumentMapper.Builder( - new RootObjectMapper.Builder("person") - .add(new ObjectMapper.Builder("name") - .add(new TextFieldMapper.Builder("first").store(true).index(false))), - indexService.mapperService()).build(indexService.mapperService()); - + DocumentMapper docMapper = createDocumentMapper(mapping(b -> {})); BytesReference json = new BytesArray("".getBytes(StandardCharsets.UTF_8)); - try { - docMapper.parse(new SourceToParse("test", "person", "1", json, XContentType.JSON)).rootDoc(); - fail("this point is never reached"); - } catch (MapperParsingException e) { - assertThat(e.getMessage(), equalTo("failed to parse, document is empty")); - } + MapperParsingException e = expectThrows(MapperParsingException.class, + () -> docMapper.parse(new SourceToParse("test", "_doc", "1", json, XContentType.JSON))); + assertThat(e.getMessage(), equalTo("failed to parse, document is empty")); } public void testNoLevel() throws Exception { - String defaultMapping = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("type").endObject().endObject()); - - DocumentMapper defaultMapper = createIndex("test").mapperService().documentMapperParser() - .parse("type", new CompressedXContent(defaultMapping)); - - ParsedDocument doc = defaultMapper.parse(new SourceToParse("test", "type", "1", BytesReference - .bytes(XContentFactory.jsonBuilder() - .startObject() - .field("test1", "value1") - .field("test2", "value2") - .startObject("inner").field("inner_field", "inner_value").endObject() - .endObject()), - XContentType.JSON)); - + DocumentMapper defaultMapper = createDocumentMapper(mapping(b -> {})); + ParsedDocument doc = defaultMapper.parse(source(b -> { + b.field("test1", "value1"); + b.field("test2", "value2"); + b.startObject("inner").field("inner_field", "inner_value").endObject(); + })); assertThat(doc.rootDoc().get("test1"), equalTo("value1")); assertThat(doc.rootDoc().get("test2"), equalTo("value2")); assertThat(doc.rootDoc().get("inner.inner_field"), equalTo("inner_value")); } + // TODO do we still need all this tests for 'type' at the bottom level now that + // we no longer have types? + public void testTypeLevel() throws Exception { - String defaultMapping = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("type").endObject().endObject()); + DocumentMapper defaultMapper = createDocumentMapper(mapping(b -> {})); - DocumentMapper defaultMapper = createIndex("test").mapperService().documentMapperParser() - .parse("type", new CompressedXContent(defaultMapping)); - - ParsedDocument doc = defaultMapper.parse(new SourceToParse("test", "type", "1", BytesReference - .bytes(XContentFactory.jsonBuilder() - .startObject().startObject("type") - .field("test1", "value1") - .field("test2", "value2") - .startObject("inner").field("inner_field", "inner_value").endObject() - .endObject().endObject()), - XContentType.JSON)); + ParsedDocument doc = defaultMapper.parse(source(b -> { + b.startObject("type"); + { + b.field("test1", "value1"); + b.field("test2", "value2"); + b.startObject("inner").field("inner_field", "inner_value").endObject(); + } + b.endObject(); + })); assertThat(doc.rootDoc().get("type.test1"), equalTo("value1")); assertThat(doc.rootDoc().get("type.test2"), equalTo("value2")); @@ -1279,20 +1056,14 @@ public class DocumentParserTests extends ESSingleNodeTestCase { } public void testNoLevelWithFieldTypeAsValue() throws Exception { - String defaultMapping = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("type").endObject().endObject()); + DocumentMapper defaultMapper = createDocumentMapper(mapping(b -> {})); - DocumentMapper defaultMapper = createIndex("test").mapperService().documentMapperParser() - .parse("type", new CompressedXContent(defaultMapping)); - - ParsedDocument doc = defaultMapper.parse(new SourceToParse("test", "type", "1", BytesReference - .bytes(XContentFactory.jsonBuilder() - .startObject() - .field("type", "value_type") - .field("test1", "value1") - .field("test2", "value2") - .startObject("inner").field("inner_field", "inner_value").endObject() - .endObject()), - XContentType.JSON)); + ParsedDocument doc = defaultMapper.parse(source(b -> { + b.field("type", "value_type"); + b.field("test1", "value1"); + b.field("test2", "value2"); + b.startObject("inner").field("inner_field", "inner_value").endObject(); + })); assertThat(doc.rootDoc().get("type"), equalTo("value_type")); assertThat(doc.rootDoc().get("test1"), equalTo("value1")); @@ -1301,20 +1072,19 @@ public class DocumentParserTests extends ESSingleNodeTestCase { } public void testTypeLevelWithFieldTypeAsValue() throws Exception { - String defaultMapping = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("type").endObject().endObject()); - DocumentMapper defaultMapper = createIndex("test").mapperService().documentMapperParser() - .parse("type", new CompressedXContent(defaultMapping)); + DocumentMapper defaultMapper = createDocumentMapper(mapping(b -> {})); - ParsedDocument doc = defaultMapper.parse(new SourceToParse("test", "type", "1", BytesReference - .bytes(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()), - XContentType.JSON)); + ParsedDocument doc = defaultMapper.parse(source(b -> { + b.startObject("type"); + { + b.field("type", "value_type"); + b.field("test1", "value1"); + b.field("test2", "value2"); + b.startObject("inner").field("inner_field", "inner_value").endObject(); + } + b.endObject(); + })); assertThat(doc.rootDoc().get("type.type"), equalTo("value_type")); assertThat(doc.rootDoc().get("type.test1"), equalTo("value1")); @@ -1323,20 +1093,14 @@ public class DocumentParserTests extends ESSingleNodeTestCase { } public void testNoLevelWithFieldTypeAsObject() throws Exception { - String defaultMapping = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("type").endObject().endObject()); + DocumentMapper defaultMapper = createDocumentMapper(mapping(b -> {})); - DocumentMapper defaultMapper = createIndex("test").mapperService().documentMapperParser() - .parse("type", new CompressedXContent(defaultMapping)); - - ParsedDocument doc = defaultMapper.parse(new SourceToParse("test", "type", "1", BytesReference - .bytes(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()), - XContentType.JSON)); + ParsedDocument doc = defaultMapper.parse(source(b -> { + b.startObject("type").field("type_field", "type_value").endObject(); + b.field("test1", "value1"); + b.field("test2", "value2"); + b.startObject("inner").field("inner_field", "inner_value").endObject(); + })); // in this case, we analyze the type object as the actual document, and ignore the other same level fields assertThat(doc.rootDoc().get("type.type_field"), equalTo("type_value")); @@ -1345,20 +1109,18 @@ public class DocumentParserTests extends ESSingleNodeTestCase { } public void testTypeLevelWithFieldTypeAsObject() throws Exception { - String defaultMapping = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("type").endObject().endObject()); + DocumentMapper defaultMapper = createDocumentMapper(mapping(b -> {})); - DocumentMapper defaultMapper = createIndex("test").mapperService().documentMapperParser() - .parse("type", new CompressedXContent(defaultMapping)); - - ParsedDocument doc = defaultMapper.parse(new SourceToParse("test", "type", "1", BytesReference - .bytes(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()), - XContentType.JSON)); + ParsedDocument doc = defaultMapper.parse(source(b -> { + b.startObject("type"); + { + b.startObject("type").field("type_field", "type_value").endObject(); + b.field("test1", "value1"); + b.field("test2", "value2"); + b.startObject("inner").field("inner_field", "inner_value").endObject(); + } + b.endObject(); + })); assertThat(doc.rootDoc().get("type.type.type_field"), equalTo("type_value")); assertThat(doc.rootDoc().get("type.test1"), equalTo("value1")); @@ -1367,64 +1129,54 @@ public class DocumentParserTests extends ESSingleNodeTestCase { } public void testNoLevelWithFieldTypeAsValueNotFirst() throws Exception { - String defaultMapping = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("type").endObject().endObject()); + DocumentMapper defaultMapper = createDocumentMapper(mapping(b -> {})); - DocumentMapper defaultMapper = createIndex("test").mapperService().documentMapperParser() - .parse("type", new CompressedXContent(defaultMapping)); + ParsedDocument doc = defaultMapper.parse(source(b -> { + b.startObject("type"); + { + b.field("test1", "value1"); + b.field("test2", "value2"); + b.field("type", "type_value"); + b.startObject("inner").field("inner_field", "inner_value").endObject(); + } + b.endObject(); + })); - ParsedDocument doc = defaultMapper.parse(new SourceToParse("test", "type", "1", BytesReference - .bytes(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()), - XContentType.JSON)); - - assertThat(doc.rootDoc().get("type.type"), equalTo("value_type")); + assertThat(doc.rootDoc().get("type.type"), equalTo("type_value")); assertThat(doc.rootDoc().get("type.test1"), equalTo("value1")); assertThat(doc.rootDoc().get("type.test2"), equalTo("value2")); assertThat(doc.rootDoc().get("type.inner.inner_field"), equalTo("inner_value")); } public void testTypeLevelWithFieldTypeAsValueNotFirst() throws Exception { - String defaultMapping = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("type").endObject().endObject()); + DocumentMapper defaultMapper = createDocumentMapper(mapping(b -> {})); - DocumentMapper defaultMapper = createIndex("test").mapperService().documentMapperParser() - .parse("type", new CompressedXContent(defaultMapping)); + ParsedDocument doc = defaultMapper.parse(source(b -> { + b.startObject("type"); + { + b.field("test1", "value1"); + b.field("type", "type_value"); + b.field("test2", "value2"); + b.startObject("inner").field("inner_field", "inner_value").endObject(); + } + b.endObject(); + })); - ParsedDocument doc = defaultMapper.parse(new SourceToParse("test", "type", "1", BytesReference - .bytes(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()), - XContentType.JSON)); - - assertThat(doc.rootDoc().get("type.type"), equalTo("value_type")); + assertThat(doc.rootDoc().get("type.type"), equalTo("type_value")); assertThat(doc.rootDoc().get("type.test1"), equalTo("value1")); assertThat(doc.rootDoc().get("type.test2"), equalTo("value2")); assertThat(doc.rootDoc().get("type.inner.inner_field"), equalTo("inner_value")); } public void testNoLevelWithFieldTypeAsObjectNotFirst() throws Exception { - String defaultMapping = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("type").endObject().endObject()); + DocumentMapper defaultMapper = createDocumentMapper(mapping(b -> {})); - DocumentMapper defaultMapper = createIndex("test").mapperService().documentMapperParser() - .parse("type", new CompressedXContent(defaultMapping)); - - ParsedDocument doc = defaultMapper.parse(new SourceToParse("test", "type", "1", BytesReference - .bytes(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()), - XContentType.JSON)); + ParsedDocument doc = defaultMapper.parse(source(b -> { + b.field("test1", "value1"); + b.startObject("type").field("type_field", "type_value").endObject(); + b.field("test2", "value2"); + b.startObject("inner").field("inner_field", "inner_value").endObject(); + })); // when the type is not the first one, we don't confuse it... assertThat(doc.rootDoc().get("type.type_field"), equalTo("type_value")); @@ -1434,20 +1186,18 @@ public class DocumentParserTests extends ESSingleNodeTestCase { } public void testTypeLevelWithFieldTypeAsObjectNotFirst() throws Exception { - String defaultMapping = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("type").endObject().endObject()); + DocumentMapper defaultMapper = createDocumentMapper(mapping(b -> {})); - DocumentMapper defaultMapper = createIndex("test").mapperService().documentMapperParser() - .parse("type", new CompressedXContent(defaultMapping)); - - ParsedDocument doc = defaultMapper.parse(new SourceToParse("test", "type", "1", BytesReference - .bytes(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()), - XContentType.JSON)); + ParsedDocument doc = defaultMapper.parse(source(b -> { + b.startObject("type"); + { + b.field("test1", "value1"); + b.startObject("type").field("type_field", "type_value").endObject(); + b.field("test2", "value2"); + b.startObject("inner").field("inner_field", "inner_value").endObject(); + } + b.endObject(); + })); assertThat(doc.rootDoc().get("type.type.type_field"), equalTo("type_value")); assertThat(doc.rootDoc().get("type.test1"), equalTo("value1")); @@ -1456,21 +1206,11 @@ public class DocumentParserTests extends ESSingleNodeTestCase { } public void testDynamicDateDetectionDisabledOnNumbers() throws IOException { - DocumentMapperParser mapperParser = createIndex("test").mapperService().documentMapperParser(); - String mapping = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("type") - .startArray("dynamic_date_formats") - .value("yyyy") - .endArray().endObject().endObject()); - DocumentMapper mapper = mapperParser.parse("type", new CompressedXContent(mapping)); - - BytesReference bytes = BytesReference.bytes(XContentFactory.jsonBuilder() - .startObject() - .field("foo", "2016") - .endObject()); + DocumentMapper mapper = createDocumentMapper(topMapping(b -> b.startArray("dynamic_date_formats").value("yyyy").endArray())); // Even though we matched the dynamic format, we do not match on numbers, // which are too likely to be false positives - ParsedDocument doc = mapper.parse(new SourceToParse("test", "type", "1", bytes, XContentType.JSON)); + ParsedDocument doc = mapper.parse(source(b -> b.field("foo", "2016"))); Mapping update = doc.dynamicMappingsUpdate(); assertNotNull(update); Mapper dateMapper = update.root().getMapper("foo"); @@ -1479,20 +1219,10 @@ public class DocumentParserTests extends ESSingleNodeTestCase { } public void testDynamicDateDetectionEnabledWithNoSpecialCharacters() throws IOException { - DocumentMapperParser mapperParser = createIndex("test").mapperService().documentMapperParser(); - String mapping = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("type") - .startArray("dynamic_date_formats") - .value("yyyy MM") - .endArray().endObject().endObject()); - DocumentMapper mapper = mapperParser.parse("type", new CompressedXContent(mapping)); - - BytesReference bytes = BytesReference.bytes(XContentFactory.jsonBuilder() - .startObject() - .field("foo", "2016 12") - .endObject()); + DocumentMapper mapper = createDocumentMapper(topMapping(b -> b.startArray("dynamic_date_formats").value("yyyy MM").endArray())); // We should have generated a date field - ParsedDocument doc = mapper.parse(new SourceToParse("test", "type", "1", bytes, XContentType.JSON)); + ParsedDocument doc = mapper.parse(source(b -> b.field("foo", "2016 12"))); Mapping update = doc.dynamicMappingsUpdate(); assertNotNull(update); Mapper dateMapper = update.root().getMapper("foo"); @@ -1501,186 +1231,153 @@ public class DocumentParserTests extends ESSingleNodeTestCase { } public void testDynamicFieldsStartingAndEndingWithDot() throws Exception { - BytesReference bytes = BytesReference.bytes(XContentFactory.jsonBuilder().startObject().startArray("top.") - .startObject().startArray("foo.") - .startObject() - .field("thing", "bah") - .endObject().endArray() - .endObject().endArray() - .endObject()); + MapperService mapperService = createMapperService(mapping(b -> {})); + merge(mapperService, dynamicMapping(mapperService.documentMapper().parse(source(b -> { + b.startArray("top."); + { + b.startObject(); + { + b.startArray("foo."); + { + b.startObject().field("thing", "bah").endObject(); + } + b.endArray(); + } + b.endObject(); + } + b.endArray(); + })).dynamicMappingsUpdate())); - client().prepareIndex("idx", "type").setSource(bytes, XContentType.JSON).get(); + IllegalArgumentException e = expectThrows(IllegalArgumentException.class, + () -> mapperService.documentMapper().parse(source(b -> { + b.startArray("top."); + { + b.startObject(); + { + b.startArray("foo."); + { + b.startObject(); + { + b.startObject("bar."); + { + b.startObject("aoeu").field("a", 1).field("b", 2).endObject(); + } + b.endObject(); + } + b.endObject(); + } + b.endArray(); + } + b.endObject(); + } + b.endArray(); + }))); - bytes = BytesReference.bytes(XContentFactory.jsonBuilder().startObject().startArray("top.") - .startObject().startArray("foo.") - .startObject() - .startObject("bar.") - .startObject("aoeu") - .field("a", 1).field("b", 2) - .endObject() - .endObject() - .endObject() - .endArray().endObject().endArray() - .endObject()); - - try { - client().prepareIndex("idx", "type").setSource(bytes, XContentType.JSON).get(); - fail("should have failed to dynamically introduce a double-dot field"); - } catch (IllegalArgumentException e) { - assertThat(e.getMessage(), + assertThat(e.getMessage(), containsString("object field starting or ending with a [.] makes object resolution ambiguous: [top..foo..bar]")); - } } public void testDynamicFieldsEmptyName() throws Exception { - BytesReference bytes = BytesReference.bytes(XContentFactory.jsonBuilder() - .startObject().startArray("top.") - .startObject() - .startObject("aoeu") - .field("a", 1).field(" ", 2) - .endObject() - .endObject().endArray() - .endObject()); + + DocumentMapper mapper = createDocumentMapper(mapping(b -> {})); IllegalArgumentException emptyFieldNameException = expectThrows(IllegalArgumentException.class, - () -> client().prepareIndex("idx", "type").setSource(bytes, XContentType.JSON).get()); + () -> mapper.parse(source(b -> { + b.startArray("top."); + { + b.startObject(); + { + b.startObject("aoeu").field("a", 1).field(" ", 2).endObject(); + } + b.endObject(); + } + b.endArray(); + }))); assertThat(emptyFieldNameException.getMessage(), containsString( "object field cannot contain only whitespace: ['top.aoeu. ']")); } public void testBlankFieldNames() throws Exception { - final BytesReference bytes = BytesReference.bytes(XContentFactory.jsonBuilder() - .startObject() - .field("", "foo") - .endObject()); + DocumentMapper mapper = createDocumentMapper(mapping(b -> {})); MapperParsingException err = expectThrows(MapperParsingException.class, () -> - client().prepareIndex("idx", "type").setSource(bytes, XContentType.JSON).get()); + mapper.parse(source(b -> b.field("", "foo")))); assertThat(err.getCause(), notNullValue()); assertThat(err.getCause().getMessage(), containsString("field name cannot be an empty string")); - final BytesReference bytes2 = BytesReference.bytes(XContentFactory.jsonBuilder() - .startObject() - .startObject("foo") - .field("", "bar") - .endObject() - .endObject()); - err = expectThrows(MapperParsingException.class, () -> - client().prepareIndex("idx", "type").setSource(bytes2, XContentType.JSON).get()); + mapper.parse(source(b -> b.startObject("foo").field("", "bar").endObject()))); assertThat(err.getCause(), notNullValue()); assertThat(err.getCause().getMessage(), containsString("field name cannot be an empty string")); } public void testWriteToFieldAlias() throws Exception { - String mapping = Strings.toString(XContentFactory.jsonBuilder() - .startObject() - .startObject("type") - .startObject("properties") - .startObject("alias-field") - .field("type", "alias") - .field("path", "concrete-field") - .endObject() - .startObject("concrete-field") - .field("type", "keyword") - .endObject() - .endObject() - .endObject() - .endObject()); + DocumentMapper mapper = createDocumentMapper(mapping(b -> { + b.startObject("alias-field"); + { + b.field("type", "alias"); + b.field("path", "concrete-field"); + } + b.endObject(); + b.startObject("concrete-field").field("type", "keyword").endObject(); + })); - DocumentMapperParser mapperParser = createIndex("test").mapperService().documentMapperParser(); - DocumentMapper mapper = mapperParser.parse("type", new CompressedXContent(mapping)); - - BytesReference bytes = BytesReference.bytes(XContentFactory.jsonBuilder() - .startObject() - .field("alias-field", "value") - .endObject()); MapperParsingException exception = expectThrows(MapperParsingException.class, - () -> mapper.parse(new SourceToParse("test", "type", "1", bytes, XContentType.JSON))); + () -> mapper.parse(source(b -> b.field("alias-field", "value")))); assertEquals("Cannot write to a field alias [alias-field].", exception.getCause().getMessage()); } public void testCopyToFieldAlias() throws Exception { - String mapping = Strings.toString(XContentFactory.jsonBuilder() - .startObject() - .startObject("type") - .startObject("properties") - .startObject("alias-field") - .field("type", "alias") - .field("path", "concrete-field") - .endObject() - .startObject("concrete-field") - .field("type", "keyword") - .endObject() - .startObject("text-field") - .field("type", "text") - .field("copy_to", "alias-field") - .endObject() - .endObject() - .endObject() - .endObject()); + DocumentMapper mapper = createDocumentMapper(mapping(b -> { + b.startObject("alias-field"); + { + b.field("type", "alias"); + b.field("path", "concrete-field"); + } + b.endObject(); + b.startObject("concrete-field").field("type", "keyword").endObject(); + b.startObject("text-field"); + { + b.field("type", "text"); + b.field("copy_to", "alias-field"); + } + b.endObject(); + })); - DocumentMapperParser mapperParser = createIndex("test").mapperService().documentMapperParser(); - DocumentMapper mapper = mapperParser.parse("type", new CompressedXContent(mapping)); - - BytesReference bytes = BytesReference.bytes(XContentFactory.jsonBuilder() - .startObject() - .field("text-field", "value") - .endObject()); MapperParsingException exception = expectThrows(MapperParsingException.class, - () -> mapper.parse(new SourceToParse("test", "type", "1", bytes, XContentType.JSON))); + () -> mapper.parse(source(b -> b.field("text-field", "value")))); assertEquals("Cannot copy to a field alias [alias-field].", exception.getCause().getMessage()); } public void testDynamicDottedFieldNameWithFieldAlias() throws Exception { - String mapping = Strings.toString(XContentFactory.jsonBuilder() - .startObject() - .startObject("type") - .startObject("properties") - .startObject("alias-field") - .field("type", "alias") - .field("path", "concrete-field") - .endObject() - .startObject("concrete-field") - .field("type", "keyword") - .endObject() - .endObject() - .endObject() - .endObject()); + DocumentMapper mapper = createDocumentMapper(mapping(b -> { + b.startObject("alias-field"); + { + b.field("type", "alias"); + b.field("path", "concrete-field"); + } + b.endObject(); + b.startObject("concrete-field").field("type", "keyword").endObject(); + })); - DocumentMapperParser mapperParser = createIndex("test").mapperService().documentMapperParser(); - DocumentMapper mapper = mapperParser.parse("type", new CompressedXContent(mapping)); - - BytesReference bytes = BytesReference.bytes(XContentFactory.jsonBuilder() - .startObject() - .startObject("alias-field.dynamic-field") - .field("type", "keyword") - .endObject() - .endObject()); MapperParsingException exception = expectThrows(MapperParsingException.class, - () -> mapper.parse(new SourceToParse("test", "type", "1", bytes, XContentType.JSON))); + () -> mapper.parse(source(b -> b.startObject("alias-field.dynamic-field").field("type", "keyword").endObject()))); assertEquals("Could not dynamically add mapping for field [alias-field.dynamic-field]. " + "Existing mapping for [alias-field] must be of type object but found [alias].", exception.getMessage()); } public void testTypeless() throws IOException { - DocumentMapperParser mapperParser = createIndex("test").mapperService().documentMapperParser(); String mapping = Strings.toString(XContentFactory.jsonBuilder() .startObject().startObject("type").startObject("properties") .startObject("foo").field("type", "keyword").endObject() .endObject().endObject().endObject()); - DocumentMapper mapper = mapperParser.parse("type", new CompressedXContent(mapping)); + DocumentMapper mapper = createDocumentMapper("type", mapping); - BytesReference bytes = BytesReference.bytes(XContentFactory.jsonBuilder() - .startObject() - .field("foo", "1234") - .endObject()); - - ParsedDocument doc = mapper.parse(new SourceToParse("test", "_doc", "1", bytes, XContentType.JSON)); + ParsedDocument doc = mapper.parse(source(b -> b.field("foo", "1234"))); assertNull(doc.dynamicMappingsUpdate()); // no update since we reused the existing type } } diff --git a/server/src/test/java/org/elasticsearch/index/mapper/DoubleIndexingDocTests.java b/server/src/test/java/org/elasticsearch/index/mapper/DoubleIndexingDocTests.java index ca571998a99..8e1d35395d1 100644 --- a/server/src/test/java/org/elasticsearch/index/mapper/DoubleIndexingDocTests.java +++ b/server/src/test/java/org/elasticsearch/index/mapper/DoubleIndexingDocTests.java @@ -18,80 +18,55 @@ */ package org.elasticsearch.index.mapper; -import org.apache.lucene.index.DirectoryReader; -import org.apache.lucene.index.IndexReader; -import org.apache.lucene.index.IndexWriter; import org.apache.lucene.search.IndexSearcher; import org.apache.lucene.search.TopDocs; -import org.apache.lucene.store.Directory; -import org.elasticsearch.common.Strings; -import org.elasticsearch.common.bytes.BytesReference; -import org.elasticsearch.common.lucene.Lucene; -import org.elasticsearch.common.xcontent.XContentFactory; -import org.elasticsearch.common.xcontent.XContentType; -import org.elasticsearch.index.IndexService; import org.elasticsearch.index.query.QueryShardContext; -import org.elasticsearch.test.ESSingleNodeTestCase; import static org.hamcrest.Matchers.equalTo; +import static org.mockito.Mockito.mock; -public class DoubleIndexingDocTests extends ESSingleNodeTestCase { +public class DoubleIndexingDocTests extends MapperServiceTestCase { public void testDoubleIndexingSameDoc() throws Exception { - Directory dir = newDirectory(); - IndexWriter writer = new IndexWriter(dir, newIndexWriterConfig(random(), Lucene.STANDARD_ANALYZER)); - String mapping = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("type") - .startObject("properties").endObject() - .endObject().endObject()); - IndexService index = createIndex("test"); - client().admin().indices().preparePutMapping("test").setType("type").setSource(mapping, XContentType.JSON).get(); - MapperService mapperService = index.mapperService(); - DocumentMapper mapper = mapperService.documentMapper(); + MapperService mapperService = createMapperService(mapping(b -> {})); - QueryShardContext context = index.newQueryShardContext(0, null, () -> 0L, null); - - ParsedDocument doc = mapper.parse(new SourceToParse("test", "type", "1", BytesReference - .bytes(XContentFactory.jsonBuilder() - .startObject() - .field("field1", "value1") - .field("field2", 1) - .field("field3", 1.1) - .field("field4", "2010-01-01") - .startArray("field5").value(1).value(2).value(3).endArray() - .endObject()), - XContentType.JSON)); + ParsedDocument doc = mapperService.documentMapper().parse(source(b -> { + b.field("field1", "value1"); + b.field("field2", 1); + b.field("field3", 1.1); + b.field("field4", "2010-01-01"); + b.startArray("field5").value(1).value(2).value(3).endArray(); + })); assertNotNull(doc.dynamicMappingsUpdate()); - client().admin().indices().preparePutMapping("test").setType("type") - .setSource(doc.dynamicMappingsUpdate().toString(), XContentType.JSON).get(); + merge(mapperService, dynamicMapping(doc.dynamicMappingsUpdate())); - writer.addDocument(doc.rootDoc()); - writer.addDocument(doc.rootDoc()); + QueryShardContext qsc = mock(QueryShardContext.class); - IndexReader reader = DirectoryReader.open(writer); - IndexSearcher searcher = new IndexSearcher(reader); + withLuceneIndex(mapperService, iw -> { + iw.addDocument(doc.rootDoc()); + iw.addDocument(doc.rootDoc()); + }, reader -> { + IndexSearcher searcher = new IndexSearcher(reader); + TopDocs topDocs = searcher.search(mapperService.fieldType("field1").termQuery("value1", qsc), 10); + assertThat(topDocs.totalHits.value, equalTo(2L)); - TopDocs topDocs = searcher.search(mapperService.fieldType("field1").termQuery("value1", context), 10); - assertThat(topDocs.totalHits.value, equalTo(2L)); + topDocs = searcher.search(mapperService.fieldType("field2").termQuery("1", qsc), 10); + assertThat(topDocs.totalHits.value, equalTo(2L)); - topDocs = searcher.search(mapperService.fieldType("field2").termQuery("1", context), 10); - assertThat(topDocs.totalHits.value, equalTo(2L)); + topDocs = searcher.search(mapperService.fieldType("field3").termQuery("1.1", qsc), 10); + assertThat(topDocs.totalHits.value, equalTo(2L)); - topDocs = searcher.search(mapperService.fieldType("field3").termQuery("1.1", context), 10); - assertThat(topDocs.totalHits.value, equalTo(2L)); + topDocs = searcher.search(mapperService.fieldType("field4").termQuery("2010-01-01", qsc), 10); + assertThat(topDocs.totalHits.value, equalTo(2L)); - topDocs = searcher.search(mapperService.fieldType("field4").termQuery("2010-01-01", context), 10); - assertThat(topDocs.totalHits.value, equalTo(2L)); + topDocs = searcher.search(mapperService.fieldType("field5").termQuery("1", qsc), 10); + assertThat(topDocs.totalHits.value, equalTo(2L)); - topDocs = searcher.search(mapperService.fieldType("field5").termQuery("1", context), 10); - assertThat(topDocs.totalHits.value, equalTo(2L)); + topDocs = searcher.search(mapperService.fieldType("field5").termQuery("2", qsc), 10); + assertThat(topDocs.totalHits.value, equalTo(2L)); - topDocs = searcher.search(mapperService.fieldType("field5").termQuery("2", context), 10); - assertThat(topDocs.totalHits.value, equalTo(2L)); - - topDocs = searcher.search(mapperService.fieldType("field5").termQuery("3", context), 10); - assertThat(topDocs.totalHits.value, equalTo(2L)); - writer.close(); - reader.close(); - dir.close(); + topDocs = searcher.search(mapperService.fieldType("field5").termQuery("3", qsc), 10); + assertThat(topDocs.totalHits.value, equalTo(2L)); + }); } } diff --git a/test/framework/src/main/java/org/elasticsearch/index/mapper/MapperServiceTestCase.java b/test/framework/src/main/java/org/elasticsearch/index/mapper/MapperServiceTestCase.java index 812ed299445..cf405cbb1d5 100644 --- a/test/framework/src/main/java/org/elasticsearch/index/mapper/MapperServiceTestCase.java +++ b/test/framework/src/main/java/org/elasticsearch/index/mapper/MapperServiceTestCase.java @@ -94,6 +94,12 @@ public abstract class MapperServiceTestCase extends ESTestCase { return createMapperService(mappings).documentMapper(); } + protected final DocumentMapper createDocumentMapper(String type, String mappings) throws IOException { + MapperService mapperService = createMapperService(mapping(b -> {})); + merge(type, mapperService, mappings); + return mapperService.documentMapper(); + } + protected final MapperService createMapperService(XContentBuilder mappings) throws IOException { return createMapperService(getIndexSettings(), mappings); } @@ -158,7 +164,29 @@ public abstract class MapperServiceTestCase extends ESTestCase { * Merge a new mapping into the one in the provided {@link MapperService}. */ protected final void merge(MapperService mapperService, XContentBuilder mapping) throws IOException { - mapperService.merge("_doc", new CompressedXContent(BytesReference.bytes(mapping)), MapperService.MergeReason.MAPPING_UPDATE); + merge(mapperService, MapperService.MergeReason.MAPPING_UPDATE, mapping); + } + + /** + * Merge a new mapping into the one in the provided {@link MapperService}. + */ + protected final void merge(String type, MapperService mapperService, String mapping) throws IOException { + mapperService.merge(type, new CompressedXContent(mapping), MapperService.MergeReason.MAPPING_UPDATE); + } + + /** + * Merge a new mapping into the one in the provided {@link MapperService} with a specific {@code MergeReason} + */ + protected final void merge(MapperService mapperService, + MapperService.MergeReason reason, + XContentBuilder mapping) throws IOException { + mapperService.merge("_doc", new CompressedXContent(BytesReference.bytes(mapping)), reason); + } + + protected final XContentBuilder topMapping(CheckedConsumer buildFields) throws IOException { + XContentBuilder builder = XContentFactory.jsonBuilder().startObject().startObject("_doc"); + buildFields.accept(builder); + return builder.endObject().endObject(); } protected final XContentBuilder mapping(CheckedConsumer buildFields) throws IOException { @@ -167,6 +195,12 @@ public abstract class MapperServiceTestCase extends ESTestCase { return builder.endObject().endObject().endObject(); } + protected final XContentBuilder dynamicMapping(Mapping dynamicMapping) throws IOException { + XContentBuilder builder = XContentFactory.jsonBuilder().startObject(); + dynamicMapping.toXContent(builder, ToXContent.EMPTY_PARAMS); + return builder.endObject(); + } + protected final XContentBuilder fieldMapping(CheckedConsumer buildField) throws IOException { return mapping(b -> { b.startObject("field");