Added a global ignore_malformed index setting. #2220 Also extended the ignore_malformed support to TTL, Ip and timestamp field types.

This commit is contained in:
Martijn van Groningen 2012-08-31 16:13:43 +02:00 committed by Shay Banon
parent 888b7cc48f
commit cd0e1226e1
14 changed files with 125 additions and 20 deletions

View File

@ -76,7 +76,7 @@ public class ByteFieldMapper extends NumberFieldMapper<Byte> {
@Override @Override
public ByteFieldMapper build(BuilderContext context) { public ByteFieldMapper build(BuilderContext context) {
ByteFieldMapper fieldMapper = new ByteFieldMapper(buildNames(context), ByteFieldMapper fieldMapper = new ByteFieldMapper(buildNames(context),
precisionStep, fuzzyFactor, index, store, boost, omitNorms, indexOptions, nullValue, ignoreMalformed); precisionStep, fuzzyFactor, index, store, boost, omitNorms, indexOptions, nullValue, ignoreMalformed(context));
fieldMapper.includeInAll(includeInAll); fieldMapper.includeInAll(includeInAll);
return fieldMapper; return fieldMapper;
} }

View File

@ -105,7 +105,7 @@ public class DateFieldMapper extends NumberFieldMapper<Long> {
} }
DateFieldMapper fieldMapper = new DateFieldMapper(buildNames(context), dateTimeFormatter, DateFieldMapper fieldMapper = new DateFieldMapper(buildNames(context), dateTimeFormatter,
precisionStep, fuzzyFactor, index, store, boost, omitNorms, indexOptions, nullValue, precisionStep, fuzzyFactor, index, store, boost, omitNorms, indexOptions, nullValue,
timeUnit, parseUpperInclusive, ignoreMalformed); timeUnit, parseUpperInclusive, ignoreMalformed(context));
fieldMapper.includeInAll(includeInAll); fieldMapper.includeInAll(includeInAll);
return fieldMapper; return fieldMapper;
} }

View File

@ -77,7 +77,7 @@ public class DoubleFieldMapper extends NumberFieldMapper<Double> {
public DoubleFieldMapper build(BuilderContext context) { public DoubleFieldMapper build(BuilderContext context) {
DoubleFieldMapper fieldMapper = new DoubleFieldMapper(buildNames(context), DoubleFieldMapper fieldMapper = new DoubleFieldMapper(buildNames(context),
precisionStep, fuzzyFactor, index, store, boost, omitNorms, indexOptions, nullValue, precisionStep, fuzzyFactor, index, store, boost, omitNorms, indexOptions, nullValue,
ignoreMalformed); ignoreMalformed(context));
fieldMapper.includeInAll(includeInAll); fieldMapper.includeInAll(includeInAll);
return fieldMapper; return fieldMapper;
} }

View File

@ -78,7 +78,7 @@ public class FloatFieldMapper extends NumberFieldMapper<Float> {
public FloatFieldMapper build(BuilderContext context) { public FloatFieldMapper build(BuilderContext context) {
FloatFieldMapper fieldMapper = new FloatFieldMapper(buildNames(context), FloatFieldMapper fieldMapper = new FloatFieldMapper(buildNames(context),
precisionStep, fuzzyFactor, index, store, boost, omitNorms, indexOptions, nullValue, precisionStep, fuzzyFactor, index, store, boost, omitNorms, indexOptions, nullValue,
ignoreMalformed); ignoreMalformed(context));
fieldMapper.includeInAll(includeInAll); fieldMapper.includeInAll(includeInAll);
return fieldMapper; return fieldMapper;
} }

View File

@ -78,7 +78,7 @@ public class IntegerFieldMapper extends NumberFieldMapper<Integer> {
public IntegerFieldMapper build(BuilderContext context) { public IntegerFieldMapper build(BuilderContext context) {
IntegerFieldMapper fieldMapper = new IntegerFieldMapper(buildNames(context), IntegerFieldMapper fieldMapper = new IntegerFieldMapper(buildNames(context),
precisionStep, fuzzyFactor, index, store, boost, omitNorms, indexOptions, precisionStep, fuzzyFactor, index, store, boost, omitNorms, indexOptions,
nullValue, ignoreMalformed); nullValue, ignoreMalformed(context));
fieldMapper.includeInAll(includeInAll); fieldMapper.includeInAll(includeInAll);
return fieldMapper; return fieldMapper;
} }

View File

@ -78,7 +78,7 @@ public class LongFieldMapper extends NumberFieldMapper<Long> {
public LongFieldMapper build(BuilderContext context) { public LongFieldMapper build(BuilderContext context) {
LongFieldMapper fieldMapper = new LongFieldMapper(buildNames(context), LongFieldMapper fieldMapper = new LongFieldMapper(buildNames(context),
precisionStep, fuzzyFactor, index, store, boost, omitNorms, indexOptions, nullValue, precisionStep, fuzzyFactor, index, store, boost, omitNorms, indexOptions, nullValue,
ignoreMalformed); ignoreMalformed(context));
fieldMapper.includeInAll(includeInAll); fieldMapper.includeInAll(includeInAll);
return fieldMapper; return fieldMapper;
} }

View File

@ -60,7 +60,7 @@ public abstract class NumberFieldMapper<T extends Number> extends AbstractFieldM
protected String fuzzyFactor = Defaults.FUZZY_FACTOR; protected String fuzzyFactor = Defaults.FUZZY_FACTOR;
protected boolean ignoreMalformed = Defaults.IGNORE_MALFORMED; private Boolean ignoreMalformed;
public Builder(String name) { public Builder(String name) {
super(name); super(name);
@ -104,6 +104,15 @@ public abstract class NumberFieldMapper<T extends Number> extends AbstractFieldM
return builder; return builder;
} }
protected boolean ignoreMalformed(BuilderContext context) {
if (ignoreMalformed != null) {
return ignoreMalformed;
}
if (context.indexSettings() != null) {
return context.indexSettings().getAsBoolean("index.mapping.ignore_malformed", Defaults.IGNORE_MALFORMED);
}
return Defaults.IGNORE_MALFORMED;
}
} }
protected int precisionStep; protected int precisionStep;

View File

@ -78,7 +78,7 @@ public class ShortFieldMapper extends NumberFieldMapper<Short> {
public ShortFieldMapper build(BuilderContext context) { public ShortFieldMapper build(BuilderContext context) {
ShortFieldMapper fieldMapper = new ShortFieldMapper(buildNames(context), ShortFieldMapper fieldMapper = new ShortFieldMapper(buildNames(context),
precisionStep, fuzzyFactor, index, store, boost, omitNorms, indexOptions, nullValue, precisionStep, fuzzyFactor, index, store, boost, omitNorms, indexOptions, nullValue,
ignoreMalformed); ignoreMalformed(context));
fieldMapper.includeInAll(includeInAll); fieldMapper.includeInAll(includeInAll);
return fieldMapper; return fieldMapper;
} }

View File

@ -75,7 +75,7 @@ public class TTLFieldMapper extends LongFieldMapper implements InternalMapper, R
@Override @Override
public TTLFieldMapper build(BuilderContext context) { public TTLFieldMapper build(BuilderContext context) {
return new TTLFieldMapper(store, index, enabled, defaultTTL); return new TTLFieldMapper(store, index, enabled, defaultTTL, ignoreMalformed(context));
} }
} }
@ -104,13 +104,13 @@ public class TTLFieldMapper extends LongFieldMapper implements InternalMapper, R
private long defaultTTL; private long defaultTTL;
public TTLFieldMapper() { public TTLFieldMapper() {
this(Defaults.STORE, Defaults.INDEX, Defaults.ENABLED, Defaults.DEFAULT); this(Defaults.STORE, Defaults.INDEX, Defaults.ENABLED, Defaults.DEFAULT, Defaults.IGNORE_MALFORMED);
} }
protected TTLFieldMapper(Field.Store store, Field.Index index, boolean enabled, long defaultTTL) { protected TTLFieldMapper(Field.Store store, Field.Index index, boolean enabled, long defaultTTL, boolean ignoreMalformed) {
super(new Names(Defaults.NAME, Defaults.NAME, Defaults.NAME, Defaults.NAME), Defaults.PRECISION_STEP, super(new Names(Defaults.NAME, Defaults.NAME, Defaults.NAME, Defaults.NAME), Defaults.PRECISION_STEP,
Defaults.FUZZY_FACTOR, index, store, Defaults.BOOST, Defaults.OMIT_NORMS, Defaults.INDEX_OPTIONS, Defaults.FUZZY_FACTOR, index, store, Defaults.BOOST, Defaults.OMIT_NORMS, Defaults.INDEX_OPTIONS,
Defaults.NULL_VALUE, Defaults.IGNORE_MALFORMED); Defaults.NULL_VALUE, ignoreMalformed);
this.enabled = enabled; this.enabled = enabled;
this.defaultTTL = defaultTTL; this.defaultTTL = defaultTTL;
} }

View File

@ -89,7 +89,7 @@ public class TimestampFieldMapper extends DateFieldMapper implements InternalMap
if (context.indexSettings() != null) { if (context.indexSettings() != null) {
parseUpperInclusive = context.indexSettings().getAsBoolean("index.mapping.date.parse_upper_inclusive", Defaults.PARSE_UPPER_INCLUSIVE); parseUpperInclusive = context.indexSettings().getAsBoolean("index.mapping.date.parse_upper_inclusive", Defaults.PARSE_UPPER_INCLUSIVE);
} }
return new TimestampFieldMapper(store, index, enabled, path, dateTimeFormatter, parseUpperInclusive); return new TimestampFieldMapper(store, index, enabled, path, dateTimeFormatter, parseUpperInclusive, ignoreMalformed(context));
} }
} }
@ -119,14 +119,15 @@ public class TimestampFieldMapper extends DateFieldMapper implements InternalMap
private final String path; private final String path;
public TimestampFieldMapper() { public TimestampFieldMapper() {
this(Defaults.STORE, Defaults.INDEX, Defaults.ENABLED, Defaults.PATH, Defaults.DATE_TIME_FORMATTER, Defaults.PARSE_UPPER_INCLUSIVE); this(Defaults.STORE, Defaults.INDEX, Defaults.ENABLED, Defaults.PATH, Defaults.DATE_TIME_FORMATTER, Defaults.PARSE_UPPER_INCLUSIVE, Defaults.IGNORE_MALFORMED);
} }
protected TimestampFieldMapper(Field.Store store, Field.Index index, boolean enabled, String path, FormatDateTimeFormatter dateTimeFormatter, boolean parseUpperInclusive) { protected TimestampFieldMapper(Field.Store store, Field.Index index, boolean enabled, String path,
FormatDateTimeFormatter dateTimeFormatter, boolean parseUpperInclusive, boolean ignoreMalformed) {
super(new Names(Defaults.NAME, Defaults.NAME, Defaults.NAME, Defaults.NAME), dateTimeFormatter, super(new Names(Defaults.NAME, Defaults.NAME, Defaults.NAME, Defaults.NAME), dateTimeFormatter,
Defaults.PRECISION_STEP, Defaults.FUZZY_FACTOR, index, store, Defaults.BOOST, Defaults.OMIT_NORMS, Defaults.INDEX_OPTIONS, Defaults.PRECISION_STEP, Defaults.FUZZY_FACTOR, index, store, Defaults.BOOST, Defaults.OMIT_NORMS, Defaults.INDEX_OPTIONS,
Defaults.NULL_VALUE, TimeUnit.MILLISECONDS /*always milliseconds*/, Defaults.NULL_VALUE, TimeUnit.MILLISECONDS /*always milliseconds*/,
parseUpperInclusive, Defaults.IGNORE_MALFORMED); parseUpperInclusive, ignoreMalformed);
this.enabled = enabled; this.enabled = enabled;
this.path = path; this.path = path;
} }

View File

@ -105,7 +105,7 @@ public class IpFieldMapper extends NumberFieldMapper<Long> {
@Override @Override
public IpFieldMapper build(BuilderContext context) { public IpFieldMapper build(BuilderContext context) {
IpFieldMapper fieldMapper = new IpFieldMapper(buildNames(context), IpFieldMapper fieldMapper = new IpFieldMapper(buildNames(context),
precisionStep, index, store, boost, omitNorms, indexOptions, nullValue); precisionStep, index, store, boost, omitNorms, indexOptions, nullValue, ignoreMalformed(context));
fieldMapper.includeInAll(includeInAll); fieldMapper.includeInAll(includeInAll);
return fieldMapper; return fieldMapper;
} }
@ -132,9 +132,9 @@ public class IpFieldMapper extends NumberFieldMapper<Long> {
protected IpFieldMapper(Names names, int precisionStep, protected IpFieldMapper(Names names, int precisionStep,
Field.Index index, Field.Store store, Field.Index index, Field.Store store,
float boost, boolean omitNorms, IndexOptions indexOptions, float boost, boolean omitNorms, IndexOptions indexOptions,
String nullValue) { String nullValue, boolean ignoreMalformed) {
super(names, precisionStep, null, index, store, boost, omitNorms, indexOptions, super(names, precisionStep, null, index, store, boost, omitNorms, indexOptions,
false, new NamedAnalyzer("_ip/" + precisionStep, new NumericIpAnalyzer(precisionStep)), ignoreMalformed, new NamedAnalyzer("_ip/" + precisionStep, new NumericIpAnalyzer(precisionStep)),
new NamedAnalyzer("_ip/max", new NumericIpAnalyzer(Integer.MAX_VALUE))); new NamedAnalyzer("_ip/max", new NumericIpAnalyzer(Integer.MAX_VALUE)));
this.nullValue = nullValue; this.nullValue = nullValue;
} }

View File

@ -22,6 +22,7 @@ package org.elasticsearch.test.unit.index.mapper;
import org.elasticsearch.common.inject.Injector; import org.elasticsearch.common.inject.Injector;
import org.elasticsearch.common.inject.ModulesBuilder; import org.elasticsearch.common.inject.ModulesBuilder;
import org.elasticsearch.common.settings.ImmutableSettings; import org.elasticsearch.common.settings.ImmutableSettings;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.settings.SettingsModule; import org.elasticsearch.common.settings.SettingsModule;
import org.elasticsearch.env.Environment; import org.elasticsearch.env.Environment;
import org.elasticsearch.env.EnvironmentModule; import org.elasticsearch.env.EnvironmentModule;
@ -44,6 +45,10 @@ public class MapperTests {
return new DocumentMapperParser(new Index("test"), newAnalysisService()); return new DocumentMapperParser(new Index("test"), newAnalysisService());
} }
public static DocumentMapperParser newParser(Settings indexSettings) {
return new DocumentMapperParser(new Index("test"), indexSettings, newAnalysisService());
}
public static MapperService newMapperService() { public static MapperService newMapperService() {
return new MapperService(new Index("test"), ImmutableSettings.Builder.EMPTY_SETTINGS, new Environment(), newAnalysisService()); return new MapperService(new Index("test"), ImmutableSettings.Builder.EMPTY_SETTINGS, new Environment(), newAnalysisService());
} }

View File

@ -19,14 +19,17 @@
package org.elasticsearch.test.unit.index.mapper.date; package org.elasticsearch.test.unit.index.mapper.date;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentFactory; import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.index.mapper.DocumentMapper; import org.elasticsearch.index.mapper.DocumentMapper;
import org.elasticsearch.index.mapper.FieldMapper; import org.elasticsearch.index.mapper.FieldMapper;
import org.elasticsearch.index.mapper.MapperParsingException;
import org.elasticsearch.index.mapper.ParsedDocument; import org.elasticsearch.index.mapper.ParsedDocument;
import org.elasticsearch.index.mapper.core.DateFieldMapper; import org.elasticsearch.index.mapper.core.DateFieldMapper;
import org.elasticsearch.test.unit.index.mapper.MapperTests; import org.elasticsearch.test.unit.index.mapper.MapperTests;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import static org.elasticsearch.common.settings.ImmutableSettings.settingsBuilder;
import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.*; import static org.hamcrest.Matchers.*;
@ -97,4 +100,68 @@ public class SimpleDateMappingTests {
assertThat(doc.rootDoc().get("date_field"), nullValue()); assertThat(doc.rootDoc().get("date_field"), nullValue());
assertThat(doc.rootDoc().get("date_field_x"), equalTo("2010-01-01")); assertThat(doc.rootDoc().get("date_field_x"), equalTo("2010-01-01"));
} }
@Test
public void testIgnoreMalformedOption() throws Exception {
String mapping = XContentFactory.jsonBuilder().startObject().startObject("type")
.startObject("properties")
.startObject("field1").field("type", "date").field("ignore_malformed", true).endObject()
.startObject("field2").field("type", "date").field("ignore_malformed", false).endObject()
.startObject("field3").field("type", "date").endObject()
.endObject()
.endObject().endObject().string();
DocumentMapper defaultMapper = MapperTests.newParser().parse(mapping);
ParsedDocument doc = defaultMapper.parse("type", "1", XContentFactory.jsonBuilder()
.startObject()
.field("field1", "a")
.field("field2", "2010-01-01")
.endObject()
.bytes());
assertThat(doc.rootDoc().getFieldable("field1"), nullValue());
assertThat(doc.rootDoc().getFieldable("field2"), notNullValue());
try {
defaultMapper.parse("type", "1", XContentFactory.jsonBuilder()
.startObject()
.field("field2", "a")
.endObject()
.bytes());
} catch (MapperParsingException e) {
assertThat(e.getCause(), instanceOf(MapperParsingException.class));
}
// Verify that the default is false
try {
defaultMapper.parse("type", "1", XContentFactory.jsonBuilder()
.startObject()
.field("field3", "a")
.endObject()
.bytes());
} catch (MapperParsingException e) {
assertThat(e.getCause(), instanceOf(MapperParsingException.class));
}
// Unless the global ignore_malformed option is set to true
Settings indexSettings = settingsBuilder().put("index.mapping.ignore_malformed", true).build();
defaultMapper = MapperTests.newParser(indexSettings).parse(mapping);
doc = defaultMapper.parse("type", "1", XContentFactory.jsonBuilder()
.startObject()
.field("field3", "a")
.endObject()
.bytes());
assertThat(doc.rootDoc().getFieldable("field3"), nullValue());
// This should still throw an exception, since field2 is specifically set to ignore_malformed=false
try {
defaultMapper.parse("type", "1", XContentFactory.jsonBuilder()
.startObject()
.field("field2", "a")
.endObject()
.bytes());
} catch (MapperParsingException e) {
assertThat(e.getCause(), instanceOf(MapperParsingException.class));
}
}
} }

View File

@ -19,6 +19,7 @@
package org.elasticsearch.test.unit.index.mapper.numeric; package org.elasticsearch.test.unit.index.mapper.numeric;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentFactory; import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.index.mapper.DocumentMapper; import org.elasticsearch.index.mapper.DocumentMapper;
import org.elasticsearch.index.mapper.FieldMapper; import org.elasticsearch.index.mapper.FieldMapper;
@ -30,6 +31,7 @@ import org.elasticsearch.index.mapper.core.StringFieldMapper;
import org.elasticsearch.test.unit.index.mapper.MapperTests; import org.elasticsearch.test.unit.index.mapper.MapperTests;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import static org.elasticsearch.common.settings.ImmutableSettings.settingsBuilder;
import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.*; import static org.hamcrest.Matchers.*;
@ -79,7 +81,7 @@ public class SimpleNumericTests {
assertThat(mapper, instanceOf(StringFieldMapper.class)); assertThat(mapper, instanceOf(StringFieldMapper.class));
} }
public void testIgnoreMalformedEnabled() throws Exception { public void testIgnoreMalformedOption() throws Exception {
String mapping = XContentFactory.jsonBuilder().startObject().startObject("type") String mapping = XContentFactory.jsonBuilder().startObject().startObject("type")
.startObject("properties") .startObject("properties")
.startObject("field1").field("type", "integer").field("ignore_malformed", true).endObject() .startObject("field1").field("type", "integer").field("ignore_malformed", true).endObject()
@ -119,6 +121,27 @@ public class SimpleNumericTests {
} catch (MapperParsingException e) { } catch (MapperParsingException e) {
assertThat(e.getCause(), instanceOf(NumberFormatException.class)); assertThat(e.getCause(), instanceOf(NumberFormatException.class));
} }
// Unless the global ignore_malformed option is set to true
Settings indexSettings = settingsBuilder().put("index.mapping.ignore_malformed", true).build();
defaultMapper = MapperTests.newParser(indexSettings).parse(mapping);
doc = defaultMapper.parse("type", "1", XContentFactory.jsonBuilder()
.startObject()
.field("field3", "a")
.endObject()
.bytes());
assertThat(doc.rootDoc().getFieldable("field3"), nullValue());
// This should still throw an exception, since field2 is specifically set to ignore_malformed=false
try {
defaultMapper.parse("type", "1", XContentFactory.jsonBuilder()
.startObject()
.field("field2", "a")
.endObject()
.bytes());
} catch (MapperParsingException e) {
assertThat(e.getCause(), instanceOf(NumberFormatException.class));
}
} }
} }