Changed the default of SourceFieldMapper's includes & excludes to be null, to support a "not specified" state, which is important now that they are update-able & merge-able

This commit is contained in:
Boaz Leskes 2013-08-18 10:44:12 +02:00
parent e83eb49a80
commit 766c787737
3 changed files with 52 additions and 19 deletions

View File

@ -136,7 +136,7 @@ public class XContentMapValues {
public static Map<String, Object> filter(Map<String, Object> map, String[] includes, String[] excludes) { public static Map<String, Object> filter(Map<String, Object> map, String[] includes, String[] excludes) {
Map<String, Object> result = Maps.newHashMap(); Map<String, Object> result = Maps.newHashMap();
filter(map, result, includes, excludes, new StringBuilder()); filter(map, result, includes == null ? Strings.EMPTY_ARRAY : includes, excludes == null ? Strings.EMPTY_ARRAY : excludes, new StringBuilder());
return result; return result;
} }

View File

@ -79,8 +79,6 @@ public class SourceFieldMapper extends AbstractFieldMapper<byte[]> implements In
FIELD_TYPE.freeze(); FIELD_TYPE.freeze();
} }
public static final String[] INCLUDES = Strings.EMPTY_ARRAY;
public static final String[] EXCLUDES = Strings.EMPTY_ARRAY;
} }
public static class Builder extends Mapper.Builder<Builder, SourceFieldMapper> { public static class Builder extends Mapper.Builder<Builder, SourceFieldMapper> {
@ -93,8 +91,8 @@ public class SourceFieldMapper extends AbstractFieldMapper<byte[]> implements In
private String format = Defaults.FORMAT; private String format = Defaults.FORMAT;
private String[] includes = Defaults.INCLUDES; private String[] includes = null;
private String[] excludes = Defaults.EXCLUDES; private String[] excludes = null;
public Builder() { public Builder() {
super(Defaults.NAME); super(Defaults.NAME);
@ -192,7 +190,7 @@ public class SourceFieldMapper extends AbstractFieldMapper<byte[]> implements In
private XContentType formatContentType; private XContentType formatContentType;
public SourceFieldMapper() { public SourceFieldMapper() {
this(Defaults.NAME, Defaults.ENABLED, Defaults.FORMAT, null, -1, Defaults.INCLUDES, Defaults.EXCLUDES); this(Defaults.NAME, Defaults.ENABLED, Defaults.FORMAT, null, -1, null, null);
} }
protected SourceFieldMapper(String name, boolean enabled, String format, Boolean compress, long compressThreshold, protected SourceFieldMapper(String name, boolean enabled, String format, Boolean compress, long compressThreshold,
@ -213,12 +211,12 @@ public class SourceFieldMapper extends AbstractFieldMapper<byte[]> implements In
} }
public String[] excludes() { public String[] excludes() {
return this.excludes; return this.excludes != null ? this.excludes : Strings.EMPTY_ARRAY;
} }
public String[] includes() { public String[] includes() {
return this.includes; return this.includes != null ? this.includes : Strings.EMPTY_ARRAY;
} }
@Override @Override
@ -267,7 +265,7 @@ public class SourceFieldMapper extends AbstractFieldMapper<byte[]> implements In
} }
BytesReference source = context.source(); BytesReference source = context.source();
boolean filtered = includes.length > 0 || excludes.length > 0; boolean filtered = (includes != null && includes.length > 0) || (excludes != null && excludes.length > 0);
if (filtered) { if (filtered) {
// we don't update the context source if we filter, we want to keep it as is... // we don't update the context source if we filter, we want to keep it as is...
@ -368,7 +366,7 @@ public class SourceFieldMapper extends AbstractFieldMapper<byte[]> implements In
@Override @Override
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
// all are defaults, no need to write it at all // all are defaults, no need to write it at all
if (enabled == Defaults.ENABLED && compress == null && compressThreshold == -1 && includes.length == 0 && excludes.length == 0) { if (enabled == Defaults.ENABLED && compress == null && compressThreshold == -1 && includes == null && excludes == null) {
return builder; return builder;
} }
builder.startObject(contentType()); builder.startObject(contentType());
@ -384,10 +382,10 @@ public class SourceFieldMapper extends AbstractFieldMapper<byte[]> implements In
if (compressThreshold != -1) { if (compressThreshold != -1) {
builder.field("compress_threshold", new ByteSizeValue(compressThreshold).toString()); builder.field("compress_threshold", new ByteSizeValue(compressThreshold).toString());
} }
if (includes.length > 0) { if (includes != null) {
builder.field("includes", includes); builder.field("includes", includes);
} }
if (excludes.length > 0) { if (excludes != null) {
builder.field("excludes", excludes); builder.field("excludes", excludes);
} }
builder.endObject(); builder.endObject();

View File

@ -121,7 +121,9 @@ public class UpdateMappingTests extends AbstractSharedClusterTest {
public void updateIncludeExclude() throws Exception { public void updateIncludeExclude() throws Exception {
createIndexMapped("test", "type", "normal", "long", "exclude", "long", "include", "long"); createIndexMapped("test", "type", "normal", "long", "exclude", "long", "include", "long");
logger.info("Index doc 1"); 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() index("test", "type", "1", JsonXContent.contentBuilder().startObject()
.field("normal", 1).field("exclude", 1).field("include", 1) .field("normal", 1).field("exclude", 1).field("include", 1)
.endObject() .endObject()
@ -139,18 +141,27 @@ public class UpdateMappingTests extends AbstractSharedClusterTest {
assertTrue(putResponse.isAcknowledged()); assertTrue(putResponse.isAcknowledged());
logger.info("Index doc 2"); // changed mapping doesn't affect indexed documents (checking backward compatibility)
index("test", "type", "2", JsonXContent.contentBuilder().startObject() 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) .field("normal", 2).field("exclude", 1).field("include", 2)
.endObject() .endObject()
); );
GetResponse getResponse = get("test", "type", "2"); // but do affect newly indexed docs
getResponse = get("test", "type", "1");
assertThat(getResponse.getSource(), hasKey("normal")); assertThat(getResponse.getSource(), hasKey("normal"));
assertThat(getResponse.getSource(), not(hasKey("exclude"))); assertThat(getResponse.getSource(), not(hasKey("exclude")));
assertThat(getResponse.getSource(), hasKey("include")); assertThat(getResponse.getSource(), hasKey("include"));
logger.info("Changing mapping to includes");
putResponse = client().admin().indices().preparePutMapping("test").setType("type").setSource( putResponse = client().admin().indices().preparePutMapping("test").setType("type").setSource(
JsonXContent.contentBuilder().startObject().startObject("type") JsonXContent.contentBuilder().startObject().startObject("type")
.startObject("_source") .startObject("_source")
@ -163,19 +174,43 @@ public class UpdateMappingTests extends AbstractSharedClusterTest {
GetMappingsResponse getMappingsResponse = client().admin().indices().prepareGetMappings("test").get(); GetMappingsResponse getMappingsResponse = client().admin().indices().prepareGetMappings("test").get();
MappingMetaData typeMapping = getMappingsResponse.getMappings().get("test").get("type"); MappingMetaData typeMapping = getMappingsResponse.getMappings().get("test").get("type");
assertThat((Map<String, Object>) typeMapping.getSourceAsMap().get("_source"), hasKey("includes")); assertThat((Map<String, Object>) typeMapping.getSourceAsMap().get("_source"), hasKey("includes"));
assertThat((Map<String, Object>) typeMapping.getSourceAsMap().get("_source"), not(hasKey("excludes"))); ArrayList<String> includes = (ArrayList<String>) ((Map<String, Object>) typeMapping.getSourceAsMap().get("_source")).get("includes");
assertThat(includes, contains("include"));
assertThat((Map<String, Object>) typeMapping.getSourceAsMap().get("_source"), hasKey("excludes"));
assertThat((ArrayList<String>) ((Map<String, Object>) typeMapping.getSourceAsMap().get("_source")).get("excludes"), emptyIterable());
index("test", "type", "3", JsonXContent.contentBuilder().startObject() logger.info("Indexing doc yet again");
index("test", "type", "1", JsonXContent.contentBuilder().startObject()
.field("normal", 3).field("exclude", 3).field("include", 3) .field("normal", 3).field("exclude", 3).field("include", 3)
.endObject() .endObject()
); );
getResponse = get("test", "type", "3"); getResponse = get("test", "type", "1");
assertThat(getResponse.getSource(), not(hasKey("normal"))); assertThat(getResponse.getSource(), not(hasKey("normal")));
assertThat(getResponse.getSource(), not(hasKey("exclude"))); assertThat(getResponse.getSource(), not(hasKey("exclude")));
assertThat(getResponse.getSource(), hasKey("include")); 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<String, Object>) typeMapping.getSourceAsMap().get("_source"), hasKey("includes"));
includes = (ArrayList<String>) ((Map<String, Object>) typeMapping.getSourceAsMap().get("_source")).get("includes");
assertThat(includes, contains("include"));
assertThat((Map<String, Object>) typeMapping.getSourceAsMap().get("_source"), hasKey("excludes"));
ArrayList<String> excludes = (ArrayList<String>) ((Map<String, Object>) typeMapping.getSourceAsMap().get("_source")).get("excludes");
assertThat(excludes, contains("*.excludes"));
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")