From d31ce434526f3477eead2597acb38ed32552ad6a Mon Sep 17 00:00:00 2001 From: Ryan Ernst Date: Thu, 14 May 2015 13:01:41 -0700 Subject: [PATCH 1/2] Mappings: Add back support for enabled/includes/excludes in _source This adds back the ability to disable _source, as well as set includes and excludes. However, it also restricts these settings to not be updateable. enabled was actually already not modifiable, but no conflict was previously given if an attempt was made to change it. This also adds a check that can be made on the source mapper to know if the the source is "complete" and can be used for purposes other than returning in search or get requests. There is one example use here in highlighting, but more need to be added in a follow up issue (eg in the update API). closes #11116 --- .../mapper/internal/SourceFieldMapper.java | 37 ++++-- .../search/highlight/HighlightPhase.java | 4 +- .../source/DefaultSourceMappingTests.java | 124 ++++++++++++++---- .../UpdateMappingIntegrationTests.java | 96 -------------- 4 files changed, 122 insertions(+), 139 deletions(-) diff --git a/src/main/java/org/elasticsearch/index/mapper/internal/SourceFieldMapper.java b/src/main/java/org/elasticsearch/index/mapper/internal/SourceFieldMapper.java index be962af9234a8..5dd55356257cb 100644 --- a/src/main/java/org/elasticsearch/index/mapper/internal/SourceFieldMapper.java +++ b/src/main/java/org/elasticsearch/index/mapper/internal/SourceFieldMapper.java @@ -54,6 +54,7 @@ import org.elasticsearch.index.mapper.core.AbstractFieldMapper; import java.io.IOException; +import java.util.Arrays; import java.util.Iterator; import java.util.List; import java.util.Map; @@ -150,7 +151,7 @@ public Mapper.Builder parse(String name, Map node, ParserContext Map.Entry entry = iterator.next(); String fieldName = Strings.toUnderscoreCase(entry.getKey()); Object fieldNode = entry.getValue(); - if (fieldName.equals("enabled") && parserContext.indexVersionCreated().before(Version.V_2_0_0)) { + if (fieldName.equals("enabled")) { builder.enabled(nodeBooleanValue(fieldNode)); iterator.remove(); } else if (fieldName.equals("compress") && parserContext.indexVersionCreated().before(Version.V_2_0_0)) { @@ -172,7 +173,7 @@ public Mapper.Builder parse(String name, Map node, ParserContext } else if ("format".equals(fieldName)) { builder.format(nodeStringValue(fieldNode, null)); iterator.remove(); - } else if (fieldName.equals("includes") && parserContext.indexVersionCreated().before(Version.V_2_0_0)) { + } else if (fieldName.equals("includes")) { List values = (List) fieldNode; String[] includes = new String[values.size()]; for (int i = 0; i < includes.length; i++) { @@ -180,7 +181,7 @@ public Mapper.Builder parse(String name, Map node, ParserContext } builder.includes(includes); iterator.remove(); - } else if (fieldName.equals("excludes") && parserContext.indexVersionCreated().before(Version.V_2_0_0)) { + } else if (fieldName.equals("excludes")) { List values = (List) fieldNode; String[] excludes = new String[values.size()]; for (int i = 0; i < excludes.length; i++) { @@ -197,11 +198,14 @@ public Mapper.Builder parse(String name, Map node, ParserContext private final boolean enabled; + /** indicates whether the source will always exist and be complete, for use by features like the update API */ + private final boolean complete; + private Boolean compress; private long compressThreshold; - private String[] includes; - private String[] excludes; + private final String[] includes; + private final String[] excludes; private String format; @@ -222,6 +226,7 @@ protected SourceFieldMapper(String name, boolean enabled, String format, Boolean this.excludes = excludes; this.format = format; this.formatContentType = format == null ? null : XContentType.fromRestContentType(format); + this.complete = enabled && includes == null && excludes == null; } public boolean enabled() { @@ -237,6 +242,10 @@ public String[] includes() { return this.includes != null ? this.includes : Strings.EMPTY_ARRAY; } + public boolean isComplete() { + return complete; + } + @Override public FieldType defaultFieldType() { return Defaults.FIELD_TYPE; @@ -420,19 +429,23 @@ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws @Override public void merge(Mapper mergeWith, MergeResult mergeResult) throws MergeMappingException { SourceFieldMapper sourceMergeWith = (SourceFieldMapper) mergeWith; - if (!mergeResult.simulate()) { + if (mergeResult.simulate()) { + if (this.enabled != sourceMergeWith.enabled) { + mergeResult.addConflict("Cannot update enabled setting for [_source]"); + } + if (Arrays.equals(this.includes, sourceMergeWith.includes) == false) { + mergeResult.addConflict("Cannot update includes setting for [_source]"); + } + if (Arrays.equals(this.excludes, sourceMergeWith.excludes) == false) { + mergeResult.addConflict("Cannot update excludes setting for [_source]"); + } + } else { if (sourceMergeWith.compress != null) { this.compress = sourceMergeWith.compress; } if (sourceMergeWith.compressThreshold != -1) { this.compressThreshold = sourceMergeWith.compressThreshold; } - if (sourceMergeWith.includes != null) { - this.includes = sourceMergeWith.includes; - } - if (sourceMergeWith.excludes != null) { - this.excludes = sourceMergeWith.excludes; - } } } } diff --git a/src/main/java/org/elasticsearch/search/highlight/HighlightPhase.java b/src/main/java/org/elasticsearch/search/highlight/HighlightPhase.java index cd3c12591f706..cb22ab3a0c8e7 100644 --- a/src/main/java/org/elasticsearch/search/highlight/HighlightPhase.java +++ b/src/main/java/org/elasticsearch/search/highlight/HighlightPhase.java @@ -86,8 +86,8 @@ public void hitExecute(SearchContext context, HitContext hitContext) { if (context.highlight().forceSource(field)) { SourceFieldMapper sourceFieldMapper = context.mapperService().documentMapper(hitContext.hit().type()).sourceMapper(); - if (!sourceFieldMapper.enabled()) { - throw new IllegalArgumentException("source is forced for fields " + fieldNamesToHighlight + " but type [" + hitContext.hit().type() + "] has disabled _source"); + if (!sourceFieldMapper.isComplete()) { + throw new IllegalArgumentException("source is forced for fields " + fieldNamesToHighlight + " but type [" + hitContext.hit().type() + "] has incomplete _source"); } } diff --git a/src/test/java/org/elasticsearch/index/mapper/source/DefaultSourceMappingTests.java b/src/test/java/org/elasticsearch/index/mapper/source/DefaultSourceMappingTests.java index 7b84424633ccc..2516a3b42a2cd 100644 --- a/src/test/java/org/elasticsearch/index/mapper/source/DefaultSourceMappingTests.java +++ b/src/test/java/org/elasticsearch/index/mapper/source/DefaultSourceMappingTests.java @@ -35,6 +35,8 @@ import org.elasticsearch.test.ElasticsearchSingleNodeTest; import org.junit.Test; +import java.io.IOException; +import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Map; @@ -42,7 +44,6 @@ import static org.hamcrest.Matchers.*; public class DefaultSourceMappingTests extends ElasticsearchSingleNodeTest { - Settings backcompatSettings = ImmutableSettings.builder().put(IndexMetaData.SETTING_VERSION_CREATED, Version.V_1_4_2.id).build(); public void testNoFormat() throws Exception { String mapping = XContentFactory.jsonBuilder().startObject().startObject("type") @@ -80,8 +81,8 @@ public void testJsonFormat() throws Exception { documentMapper = parser.parse(mapping); doc = documentMapper.parse("type", "1", XContentFactory.smileBuilder().startObject() - .field("field", "value") - .endObject().bytes()); + .field("field", "value") + .endObject().bytes()); assertThat(XContentFactory.xContentType(doc.source()), equalTo(XContentType.JSON)); } @@ -91,6 +92,7 @@ public void testJsonFormatCompressedBackcompat() throws Exception { .startObject("_source").field("format", "json").field("compress", true).endObject() .endObject().endObject().string(); + Settings backcompatSettings = ImmutableSettings.builder().put(IndexMetaData.SETTING_VERSION_CREATED, Version.V_1_4_2.id).build(); DocumentMapperParser parser = createIndex("test", backcompatSettings).mapperService().documentMapperParser(); DocumentMapper documentMapper = parser.parse(mapping); ParsedDocument doc = documentMapper.parse("type", "1", XContentFactory.jsonBuilder().startObject() @@ -111,19 +113,12 @@ public void testJsonFormatCompressedBackcompat() throws Exception { assertThat(XContentFactory.xContentType(uncompressed), equalTo(XContentType.JSON)); } - public void testIncludesBackcompat() throws Exception { + public void testIncludes() throws Exception { String mapping = XContentFactory.jsonBuilder().startObject().startObject("type") .startObject("_source").field("includes", new String[]{"path1*"}).endObject() .endObject().endObject().string(); - try { - createIndex("testbad").mapperService().documentMapperParser().parse(mapping); - fail("includes should not be allowed"); - } catch (MapperParsingException e) { - assertTrue(e.getMessage().contains("unsupported parameters")); - } - - DocumentMapper documentMapper = createIndex("test", backcompatSettings).mapperService().documentMapperParser().parse(mapping); + DocumentMapper documentMapper = createIndex("test").mapperService().documentMapperParser().parse(mapping); ParsedDocument doc = documentMapper.parse("type", "1", XContentFactory.jsonBuilder().startObject() .startObject("path1").field("field1", "value1").endObject() @@ -136,19 +131,12 @@ public void testIncludesBackcompat() throws Exception { assertThat(sourceAsMap.containsKey("path2"), equalTo(false)); } - public void testExcludesBackcompat() throws Exception { + public void testExcludes() throws Exception { String mapping = XContentFactory.jsonBuilder().startObject().startObject("type") .startObject("_source").field("excludes", new String[]{"path1*"}).endObject() .endObject().endObject().string(); - try { - createIndex("testbad").mapperService().documentMapperParser().parse(mapping); - fail("excludes should not be allowed"); - } catch (MapperParsingException e) { - assertTrue(e.getMessage().contains("unsupported parameters")); - } - - DocumentMapper documentMapper = createIndex("test", backcompatSettings).mapperService().documentMapperParser().parse(mapping); + DocumentMapper documentMapper = createIndex("test").mapperService().documentMapperParser().parse(mapping); ParsedDocument doc = documentMapper.parse("type", "1", XContentFactory.jsonBuilder().startObject() .startObject("path1").field("field1", "value1").endObject() @@ -161,12 +149,12 @@ public void testExcludesBackcompat() throws Exception { assertThat(sourceAsMap.containsKey("path2"), equalTo(true)); } - public void testDefaultMappingAndNoMappingBackcompat() throws Exception { + public void testDefaultMappingAndNoMapping() throws Exception { String defaultMapping = XContentFactory.jsonBuilder().startObject().startObject(MapperService.DEFAULT_MAPPING) .startObject("_source").field("enabled", false).endObject() .endObject().endObject().string(); - DocumentMapperParser parser = createIndex("test", backcompatSettings).mapperService().documentMapperParser(); + DocumentMapperParser parser = createIndex("test").mapperService().documentMapperParser(); DocumentMapper mapper = parser.parse("my_type", null, defaultMapping); assertThat(mapper.type(), equalTo("my_type")); assertThat(mapper.sourceMapper().enabled(), equalTo(false)); @@ -189,7 +177,7 @@ public void testDefaultMappingAndNoMappingBackcompat() throws Exception { } } - public void testDefaultMappingAndWithMappingOverrideBackcompat() throws Exception { + public void testDefaultMappingAndWithMappingOverride() throws Exception { String defaultMapping = XContentFactory.jsonBuilder().startObject().startObject(MapperService.DEFAULT_MAPPING) .startObject("_source").field("enabled", false).endObject() .endObject().endObject().string(); @@ -198,17 +186,17 @@ public void testDefaultMappingAndWithMappingOverrideBackcompat() throws Exceptio .startObject("_source").field("enabled", true).endObject() .endObject().endObject().string(); - DocumentMapper mapper = createIndex("test", backcompatSettings).mapperService().documentMapperParser().parse("my_type", mapping, defaultMapping); + DocumentMapper mapper = createIndex("test").mapperService().documentMapperParser().parse("my_type", mapping, defaultMapping); assertThat(mapper.type(), equalTo("my_type")); assertThat(mapper.sourceMapper().enabled(), equalTo(true)); } - public void testDefaultMappingAndNoMappingWithMapperServiceBackcompat() throws Exception { + public void testDefaultMappingAndNoMappingWithMapperService() throws Exception { String defaultMapping = XContentFactory.jsonBuilder().startObject().startObject(MapperService.DEFAULT_MAPPING) .startObject("_source").field("enabled", false).endObject() .endObject().endObject().string(); - MapperService mapperService = createIndex("test", backcompatSettings).mapperService(); + MapperService mapperService = createIndex("test").mapperService(); mapperService.merge(MapperService.DEFAULT_MAPPING, new CompressedString(defaultMapping), true); DocumentMapper mapper = mapperService.documentMapperWithAutoCreate("my_type").v1(); @@ -216,12 +204,12 @@ public void testDefaultMappingAndNoMappingWithMapperServiceBackcompat() throws E assertThat(mapper.sourceMapper().enabled(), equalTo(false)); } - public void testDefaultMappingAndWithMappingOverrideWithMapperServiceBackcompat() throws Exception { + public void testDefaultMappingAndWithMappingOverrideWithMapperService() throws Exception { String defaultMapping = XContentFactory.jsonBuilder().startObject().startObject(MapperService.DEFAULT_MAPPING) .startObject("_source").field("enabled", false).endObject() .endObject().endObject().string(); - MapperService mapperService = createIndex("test", backcompatSettings).mapperService(); + MapperService mapperService = createIndex("test").mapperService(); mapperService.merge(MapperService.DEFAULT_MAPPING, new CompressedString(defaultMapping), true); String mapping = XContentFactory.jsonBuilder().startObject().startObject("my_type") @@ -233,4 +221,82 @@ public void testDefaultMappingAndWithMappingOverrideWithMapperServiceBackcompat( assertThat(mapper.type(), equalTo("my_type")); assertThat(mapper.sourceMapper().enabled(), equalTo(true)); } + + void assertConflicts(String mapping1, String mapping2, DocumentMapperParser parser, String... conflicts) throws IOException { + DocumentMapper docMapper = parser.parse(mapping1); + docMapper.refreshSource(); + docMapper = parser.parse(docMapper.mappingSource().string()); + MergeResult mergeResult = docMapper.merge(parser.parse(mapping2).mapping(), true); + + List expectedConflicts = new ArrayList<>(Arrays.asList(conflicts)); + for (String conflict : mergeResult.buildConflicts()) { + assertTrue("found unexpected conflict [" + conflict + "]", expectedConflicts.remove(conflict)); + } + assertTrue("missing conflicts: " + Arrays.toString(expectedConflicts.toArray()), expectedConflicts.isEmpty()); + } + + public void testEnabledNotUpdateable() throws Exception { + DocumentMapperParser parser = createIndex("test").mapperService().documentMapperParser(); + // using default of true + String mapping1 = XContentFactory.jsonBuilder().startObject().startObject("type").endObject().endObject().string(); + String mapping2 = XContentFactory.jsonBuilder().startObject().startObject("type") + .startObject("_source").field("enabled", false).endObject() + .endObject().endObject().string(); + assertConflicts(mapping1, mapping2, parser, "Cannot update enabled setting for [_source]"); + + // not changing is ok + String mapping3 = XContentFactory.jsonBuilder().startObject().startObject("type") + .startObject("_source").field("enabled", true).endObject() + .endObject().endObject().string(); + assertConflicts(mapping1, mapping3, parser); + } + + public void testIncludesNotUpdateable() throws Exception { + DocumentMapperParser parser = createIndex("test").mapperService().documentMapperParser(); + String mapping1 = XContentFactory.jsonBuilder().startObject().startObject("type") + .startObject("_source").array("includes", "foo.*").endObject() + .endObject().endObject().string(); + String mapping2 = XContentFactory.jsonBuilder().startObject().startObject("type") + .startObject("_source").array("includes", "foo.*", "bar.*").endObject() + .endObject().endObject().string(); + assertConflicts(mapping1, mapping2, parser, "Cannot update includes setting for [_source]"); + + // not changing is ok + assertConflicts(mapping1, mapping1, parser); + } + + public void testExcludesNotUpdateable() throws Exception { + DocumentMapperParser parser = createIndex("test").mapperService().documentMapperParser(); + String mapping1 = XContentFactory.jsonBuilder().startObject().startObject("type") + .startObject("_source").array("excludes", "foo.*").endObject() + .endObject().endObject().string(); + String mapping2 = XContentFactory.jsonBuilder().startObject().startObject("type") + .startObject("_source").array("excludes", "foo.*", "bar.*").endObject() + .endObject().endObject().string(); + assertConflicts(mapping1, mapping2, parser, "Cannot update excludes setting for [_source]"); + + // not changing is ok + assertConflicts(mapping1, mapping1, parser); + } + + public void testComplete() throws Exception { + DocumentMapperParser parser = createIndex("test").mapperService().documentMapperParser(); + String mapping = XContentFactory.jsonBuilder().startObject().startObject("type").endObject().endObject().string(); + assertTrue(parser.parse(mapping).sourceMapper().isComplete()); + + mapping = XContentFactory.jsonBuilder().startObject().startObject("type") + .startObject("_source").field("enabled", false).endObject() + .endObject().endObject().string(); + assertFalse(parser.parse(mapping).sourceMapper().isComplete()); + + mapping = XContentFactory.jsonBuilder().startObject().startObject("type") + .startObject("_source").array("includes", "foo.*").endObject() + .endObject().endObject().string(); + assertFalse(parser.parse(mapping).sourceMapper().isComplete()); + + mapping = XContentFactory.jsonBuilder().startObject().startObject("type") + .startObject("_source").array("excludes", "foo.*").endObject() + .endObject().endObject().string(); + assertFalse(parser.parse(mapping).sourceMapper().isComplete()); + } } diff --git a/src/test/java/org/elasticsearch/indices/mapping/UpdateMappingIntegrationTests.java b/src/test/java/org/elasticsearch/indices/mapping/UpdateMappingIntegrationTests.java index 03c8bbe56e1d4..dca5183a47100 100644 --- a/src/test/java/org/elasticsearch/indices/mapping/UpdateMappingIntegrationTests.java +++ b/src/test/java/org/elasticsearch/indices/mapping/UpdateMappingIntegrationTests.java @@ -212,102 +212,6 @@ public void updateMappingNoChanges() throws Exception { assertThat(putMappingResponse.isAcknowledged(), equalTo(true)); } - - @SuppressWarnings("unchecked") - @Test - public void updateIncludeExcludeBackcompat() throws Exception { - assertAcked(prepareCreate("test").setSettings(IndexMetaData.SETTING_VERSION_CREATED, Version.V_1_4_2.id) - .addMapping("type", jsonBuilder().startObject().startObject("type").startObject("properties") - .startObject("normal").field("type", "long").endObject() - .startObject("exclude").field("type", "long").endObject() - .startObject("include").field("type", "long").endObject() - .endObject().endObject().endObject())); - ensureGreen(); // make sure that replicas are initialized so the refresh command will work them too - - logger.info("Index doc"); - index("test", "type", "1", JsonXContent.contentBuilder().startObject() - .field("normal", 1).field("exclude", 1).field("include", 1) - .endObject() - ); - refresh(); // commit it for later testing. - - logger.info("Adding exclude settings"); - PutMappingResponse putResponse = client().admin().indices().preparePutMapping("test").setType("type").setSource( - JsonXContent.contentBuilder().startObject().startObject("type") - .startObject("_source") - .startArray("excludes").value("exclude").endArray() - .endObject().endObject() - ).get(); - - assertTrue(putResponse.isAcknowledged()); - - // changed mapping doesn't affect indexed documents (checking backward compatibility) - GetResponse getResponse = client().prepareGet("test", "type", "1").setRealtime(false).get(); - assertThat(getResponse.getSource(), hasKey("normal")); - assertThat(getResponse.getSource(), hasKey("exclude")); - assertThat(getResponse.getSource(), hasKey("include")); - - - logger.info("Index doc again"); - index("test", "type", "1", JsonXContent.contentBuilder().startObject() - .field("normal", 2).field("exclude", 1).field("include", 2) - .endObject() - ); - - // but do affect newly indexed docs - getResponse = get("test", "type", "1"); - assertThat(getResponse.getSource(), hasKey("normal")); - assertThat(getResponse.getSource(), not(hasKey("exclude"))); - assertThat(getResponse.getSource(), hasKey("include")); - - logger.info("Changing mapping to includes"); - putResponse = client().admin().indices().preparePutMapping("test").setType("type").setSource( - JsonXContent.contentBuilder().startObject().startObject("type") - .startObject("_source") - .startArray("excludes").endArray() - .startArray("includes").value("include").endArray() - .endObject().endObject() - ).get(); - assertTrue(putResponse.isAcknowledged()); - - GetMappingsResponse getMappingsResponse = client().admin().indices().prepareGetMappings("test").get(); - MappingMetaData typeMapping = getMappingsResponse.getMappings().get("test").get("type"); - assertThat((Map) typeMapping.getSourceAsMap().get("_source"), hasKey("includes")); - ArrayList includes = (ArrayList) ((Map) typeMapping.getSourceAsMap().get("_source")).get("includes"); - assertThat(includes, contains("include")); - assertThat((Map) typeMapping.getSourceAsMap().get("_source"), hasKey("excludes")); - assertThat((ArrayList) ((Map) typeMapping.getSourceAsMap().get("_source")).get("excludes"), emptyIterable()); - - logger.info("Indexing doc yet again"); - index("test", "type", "1", JsonXContent.contentBuilder().startObject() - .field("normal", 3).field("exclude", 3).field("include", 3) - .endObject() - ); - - getResponse = get("test", "type", "1"); - assertThat(getResponse.getSource(), not(hasKey("normal"))); - assertThat(getResponse.getSource(), not(hasKey("exclude"))); - assertThat(getResponse.getSource(), hasKey("include")); - - logger.info("Adding excludes, but keep includes"); - putResponse = client().admin().indices().preparePutMapping("test").setType("type").setSource( - JsonXContent.contentBuilder().startObject().startObject("type") - .startObject("_source") - .startArray("excludes").value("*.excludes").endArray() - .endObject().endObject() - ).get(); - assertTrue(putResponse.isAcknowledged()); - - getMappingsResponse = client().admin().indices().prepareGetMappings("test").get(); - typeMapping = getMappingsResponse.getMappings().get("test").get("type"); - assertThat((Map) typeMapping.getSourceAsMap().get("_source"), hasKey("includes")); - includes = (ArrayList) ((Map) typeMapping.getSourceAsMap().get("_source")).get("includes"); - assertThat(includes, contains("include")); - assertThat((Map) typeMapping.getSourceAsMap().get("_source"), hasKey("excludes")); - ArrayList excludes = (ArrayList) ((Map) typeMapping.getSourceAsMap().get("_source")).get("excludes"); - assertThat(excludes, contains("*.excludes")); - } - @SuppressWarnings("unchecked") @Test public void updateDefaultMappingSettings() throws Exception { From 0e14c6d2568c5e5ab15985fb525fb18c295a87f3 Mon Sep 17 00:00:00 2001 From: Ryan Ernst Date: Thu, 14 May 2015 14:36:26 -0700 Subject: [PATCH 2/2] Fix includes/excludes to be handled on merge conflict checking when they are null --- .../index/mapper/internal/SourceFieldMapper.java | 14 +++++++------- .../mapper/source/DefaultSourceMappingTests.java | 8 ++++++++ 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/src/main/java/org/elasticsearch/index/mapper/internal/SourceFieldMapper.java b/src/main/java/org/elasticsearch/index/mapper/internal/SourceFieldMapper.java index 5dd55356257cb..26513ddaeb64c 100644 --- a/src/main/java/org/elasticsearch/index/mapper/internal/SourceFieldMapper.java +++ b/src/main/java/org/elasticsearch/index/mapper/internal/SourceFieldMapper.java @@ -222,24 +222,24 @@ protected SourceFieldMapper(String name, boolean enabled, String format, Boolean this.enabled = enabled; this.compress = compress; this.compressThreshold = compressThreshold; - this.includes = includes; - this.excludes = excludes; + this.includes = includes == null ? Strings.EMPTY_ARRAY : includes; + this.excludes = excludes == null ? Strings.EMPTY_ARRAY : excludes; this.format = format; this.formatContentType = format == null ? null : XContentType.fromRestContentType(format); this.complete = enabled && includes == null && excludes == null; } public boolean enabled() { - return this.enabled; + return enabled; } public String[] excludes() { - return this.excludes != null ? this.excludes : Strings.EMPTY_ARRAY; + return excludes; } public String[] includes() { - return this.includes != null ? this.includes : Strings.EMPTY_ARRAY; + return includes; } public boolean isComplete() { @@ -433,10 +433,10 @@ public void merge(Mapper mergeWith, MergeResult mergeResult) throws MergeMapping if (this.enabled != sourceMergeWith.enabled) { mergeResult.addConflict("Cannot update enabled setting for [_source]"); } - if (Arrays.equals(this.includes, sourceMergeWith.includes) == false) { + if (Arrays.equals(includes, sourceMergeWith.includes) == false) { mergeResult.addConflict("Cannot update includes setting for [_source]"); } - if (Arrays.equals(this.excludes, sourceMergeWith.excludes) == false) { + if (Arrays.equals(excludes, sourceMergeWith.excludes) == false) { mergeResult.addConflict("Cannot update excludes setting for [_source]"); } } else { diff --git a/src/test/java/org/elasticsearch/index/mapper/source/DefaultSourceMappingTests.java b/src/test/java/org/elasticsearch/index/mapper/source/DefaultSourceMappingTests.java index 2516a3b42a2cd..25ab2a5c6c08e 100644 --- a/src/test/java/org/elasticsearch/index/mapper/source/DefaultSourceMappingTests.java +++ b/src/test/java/org/elasticsearch/index/mapper/source/DefaultSourceMappingTests.java @@ -253,9 +253,13 @@ public void testEnabledNotUpdateable() throws Exception { public void testIncludesNotUpdateable() throws Exception { DocumentMapperParser parser = createIndex("test").mapperService().documentMapperParser(); + String defaultMapping = XContentFactory.jsonBuilder().startObject().startObject("type").endObject().endObject().string(); String mapping1 = XContentFactory.jsonBuilder().startObject().startObject("type") .startObject("_source").array("includes", "foo.*").endObject() .endObject().endObject().string(); + assertConflicts(defaultMapping, mapping1, parser, "Cannot update includes setting for [_source]"); + assertConflicts(mapping1, defaultMapping, parser, "Cannot update includes setting for [_source]"); + String mapping2 = XContentFactory.jsonBuilder().startObject().startObject("type") .startObject("_source").array("includes", "foo.*", "bar.*").endObject() .endObject().endObject().string(); @@ -267,9 +271,13 @@ public void testIncludesNotUpdateable() throws Exception { public void testExcludesNotUpdateable() throws Exception { DocumentMapperParser parser = createIndex("test").mapperService().documentMapperParser(); + String defaultMapping = XContentFactory.jsonBuilder().startObject().startObject("type").endObject().endObject().string(); String mapping1 = XContentFactory.jsonBuilder().startObject().startObject("type") .startObject("_source").array("excludes", "foo.*").endObject() .endObject().endObject().string(); + assertConflicts(defaultMapping, mapping1, parser, "Cannot update excludes setting for [_source]"); + assertConflicts(mapping1, defaultMapping, parser, "Cannot update excludes setting for [_source]"); + String mapping2 = XContentFactory.jsonBuilder().startObject().startObject("type") .startObject("_source").array("excludes", "foo.*", "bar.*").endObject() .endObject().endObject().string();