rename and document "index.mapping.date.parse_upper_inclusive" setting for date fields

The setting causes the upper bound for a range query/filter to be rounded up,
therefore the name `round_ceil` seems to make more sense.

Also this commit removes the redundant fourth parameter to DateMathParser.parse(..)
which was never used.
was:    parse(String text, long now, boolean roundUp, boolean upperInclusive)
is now: parse(String text, long now, boolean roundCeil)

closes #3914
This commit is contained in:
Britta Weber 2013-10-15 17:28:35 +02:00
parent 2e8bbe9e30
commit c9dab6991e
6 changed files with 41 additions and 28 deletions

View File

@ -39,6 +39,10 @@ Note, when doing `range` type searches, and the upper value is
inclusive, the rounding will properly be rounded to the ceiling instead inclusive, the rounding will properly be rounded to the ceiling instead
of flooring it. of flooring it.
To change this behavior, set
`"mapping.date.round_ceil": false`.
[float] [float]
[[built-in]] [[built-in]]
=== Built In Formats === Built In Formats

View File

@ -20,14 +20,14 @@ public class DateMathParser {
} }
public long parse(String text, long now) { public long parse(String text, long now) {
return parse(text, now, false, false); return parse(text, now, false);
} }
public long parseUpperInclusive(String text, long now) { public long parseRoundCeil(String text, long now) {
return parse(text, now, true, true); return parse(text, now, true);
} }
public long parse(String text, long now, boolean roundUp, boolean upperInclusive) { public long parse(String text, long now, boolean roundCeil) {
long time; long time;
String mathString; String mathString;
if (text.startsWith("now")) { if (text.startsWith("now")) {
@ -43,8 +43,8 @@ public class DateMathParser {
parseString = text.substring(0, index); parseString = text.substring(0, index);
mathString = text.substring(index + 2); mathString = text.substring(index + 2);
} }
if (upperInclusive) { if (roundCeil) {
time = parseUpperInclusiveStringValue(parseString); time = parseRoundCeilStringValue(parseString);
} else { } else {
time = parseStringValue(parseString); time = parseStringValue(parseString);
} }
@ -54,7 +54,7 @@ public class DateMathParser {
return time; return time;
} }
return parseMath(mathString, time, roundUp); return parseMath(mathString, time, roundCeil);
} }
private long parseMath(String mathString, long time, boolean roundUp) throws ElasticSearchParseException { private long parseMath(String mathString, long time, boolean roundUp) throws ElasticSearchParseException {
@ -209,7 +209,7 @@ public class DateMathParser {
} }
} }
private long parseUpperInclusiveStringValue(String value) { private long parseRoundCeilStringValue(String value) {
try { try {
// we create a date time for inclusive upper range, we "include" by default the day level data // we create a date time for inclusive upper range, we "include" by default the day level data
// so something like 2011-01-01 will include the full first day of 2011. // so something like 2011-01-01 will include the full first day of 2011.

View File

@ -81,7 +81,7 @@ public class DateFieldMapper extends NumberFieldMapper<Long> {
public static final String NULL_VALUE = null; public static final String NULL_VALUE = null;
public static final TimeUnit TIME_UNIT = TimeUnit.MILLISECONDS; public static final TimeUnit TIME_UNIT = TimeUnit.MILLISECONDS;
public static final boolean PARSE_UPPER_INCLUSIVE = true; public static final boolean ROUND_CEIL = true;
} }
public static class Builder extends NumberFieldMapper.Builder<Builder, DateFieldMapper> { public static class Builder extends NumberFieldMapper.Builder<Builder, DateFieldMapper> {
@ -118,16 +118,17 @@ public class DateFieldMapper extends NumberFieldMapper<Long> {
@Override @Override
public DateFieldMapper build(BuilderContext context) { public DateFieldMapper build(BuilderContext context) {
boolean parseUpperInclusive = Defaults.PARSE_UPPER_INCLUSIVE; boolean roundCeil = Defaults.ROUND_CEIL;
if (context.indexSettings() != null) { if (context.indexSettings() != null) {
parseUpperInclusive = context.indexSettings().getAsBoolean("index.mapping.date.parse_upper_inclusive", Defaults.PARSE_UPPER_INCLUSIVE); Settings settings = context.indexSettings();
roundCeil = settings.getAsBoolean("index.mapping.date.round_ceil", settings.getAsBoolean("index.mapping.date.parse_upper_inclusive", Defaults.ROUND_CEIL));
} }
fieldType.setOmitNorms(fieldType.omitNorms() && boost == 1.0f); fieldType.setOmitNorms(fieldType.omitNorms() && boost == 1.0f);
if (!locale.equals(dateTimeFormatter.locale())) { if (!locale.equals(dateTimeFormatter.locale())) {
dateTimeFormatter = new FormatDateTimeFormatter(dateTimeFormatter.format(), dateTimeFormatter.parser(), dateTimeFormatter.printer(), locale); dateTimeFormatter = new FormatDateTimeFormatter(dateTimeFormatter.format(), dateTimeFormatter.parser(), dateTimeFormatter.printer(), locale);
} }
DateFieldMapper fieldMapper = new DateFieldMapper(buildNames(context), dateTimeFormatter, DateFieldMapper fieldMapper = new DateFieldMapper(buildNames(context), dateTimeFormatter,
precisionStep, boost, fieldType, nullValue, timeUnit, parseUpperInclusive, ignoreMalformed(context), precisionStep, boost, fieldType, nullValue, timeUnit, roundCeil, ignoreMalformed(context),
postingsProvider, docValuesProvider, similarity, fieldDataSettings, context.indexSettings()); postingsProvider, docValuesProvider, similarity, fieldDataSettings, context.indexSettings());
fieldMapper.includeInAll(includeInAll); fieldMapper.includeInAll(includeInAll);
return fieldMapper; return fieldMapper;
@ -184,7 +185,14 @@ public class DateFieldMapper extends NumberFieldMapper<Long> {
protected final FormatDateTimeFormatter dateTimeFormatter; protected final FormatDateTimeFormatter dateTimeFormatter;
private final boolean parseUpperInclusive; // Triggers rounding up of the upper bound for range queries and filters if
// set to true.
// Rounding up a date here has the following meaning: If a date is not
// defined with full precision, for example, no milliseconds given, the date
// will be filled up to the next larger date with that precision.
// Example: An upper bound given as "2000-01-01", will be converted to
// "2000-01-01T23.59.59.999"
private final boolean roundCeil;
private final DateMathParser dateMathParser; private final DateMathParser dateMathParser;
@ -193,7 +201,7 @@ public class DateFieldMapper extends NumberFieldMapper<Long> {
protected final TimeUnit timeUnit; protected final TimeUnit timeUnit;
protected DateFieldMapper(Names names, FormatDateTimeFormatter dateTimeFormatter, int precisionStep, float boost, FieldType fieldType, protected DateFieldMapper(Names names, FormatDateTimeFormatter dateTimeFormatter, int precisionStep, float boost, FieldType fieldType,
String nullValue, TimeUnit timeUnit, boolean parseUpperInclusive, Explicit<Boolean> ignoreMalformed, String nullValue, TimeUnit timeUnit, boolean roundCeil, Explicit<Boolean> ignoreMalformed,
PostingsFormatProvider postingsProvider, DocValuesFormatProvider docValuesProvider, SimilarityProvider similarity, PostingsFormatProvider postingsProvider, DocValuesFormatProvider docValuesProvider, SimilarityProvider similarity,
@Nullable Settings fieldDataSettings, Settings indexSettings) { @Nullable Settings fieldDataSettings, Settings indexSettings) {
super(names, precisionStep, boost, fieldType, ignoreMalformed, new NamedAnalyzer("_date/" + precisionStep, super(names, precisionStep, boost, fieldType, ignoreMalformed, new NamedAnalyzer("_date/" + precisionStep,
@ -203,7 +211,7 @@ public class DateFieldMapper extends NumberFieldMapper<Long> {
this.dateTimeFormatter = dateTimeFormatter; this.dateTimeFormatter = dateTimeFormatter;
this.nullValue = nullValue; this.nullValue = nullValue;
this.timeUnit = timeUnit; this.timeUnit = timeUnit;
this.parseUpperInclusive = parseUpperInclusive; this.roundCeil = roundCeil;
this.dateMathParser = new DateMathParser(dateTimeFormatter, timeUnit); this.dateMathParser = new DateMathParser(dateTimeFormatter, timeUnit);
} }
@ -305,7 +313,7 @@ public class DateFieldMapper extends NumberFieldMapper<Long> {
public long parseToMilliseconds(Object value, @Nullable QueryParseContext context, boolean includeUpper) { public long parseToMilliseconds(Object value, @Nullable QueryParseContext context, boolean includeUpper) {
long now = context == null ? System.currentTimeMillis() : context.nowInMillis(); long now = context == null ? System.currentTimeMillis() : context.nowInMillis();
return includeUpper ? dateMathParser.parseUpperInclusive(convertToString(value), now) : dateMathParser.parse(convertToString(value), now); return includeUpper && roundCeil ? dateMathParser.parseRoundCeil(convertToString(value), now) : dateMathParser.parse(convertToString(value), now);
} }
@Override @Override
@ -319,7 +327,7 @@ public class DateFieldMapper extends NumberFieldMapper<Long> {
public Query rangeQuery(Object lowerTerm, Object upperTerm, boolean includeLower, boolean includeUpper, @Nullable QueryParseContext context) { public Query rangeQuery(Object lowerTerm, Object upperTerm, boolean includeLower, boolean includeUpper, @Nullable QueryParseContext context) {
return NumericRangeQuery.newLongRange(names.indexName(), precisionStep, return NumericRangeQuery.newLongRange(names.indexName(), precisionStep,
lowerTerm == null ? null : parseToMilliseconds(lowerTerm, context), lowerTerm == null ? null : parseToMilliseconds(lowerTerm, context),
upperTerm == null ? null : parseToMilliseconds(upperTerm, context, includeUpper && parseUpperInclusive), upperTerm == null ? null : parseToMilliseconds(upperTerm, context, includeUpper),
includeLower, includeUpper); includeLower, includeUpper);
} }
@ -327,7 +335,7 @@ public class DateFieldMapper extends NumberFieldMapper<Long> {
public Filter rangeFilter(Object lowerTerm, Object upperTerm, boolean includeLower, boolean includeUpper, @Nullable QueryParseContext context) { public Filter rangeFilter(Object lowerTerm, Object upperTerm, boolean includeLower, boolean includeUpper, @Nullable QueryParseContext context) {
return NumericRangeFilter.newLongRange(names.indexName(), precisionStep, return NumericRangeFilter.newLongRange(names.indexName(), precisionStep,
lowerTerm == null ? null : parseToMilliseconds(lowerTerm, context), lowerTerm == null ? null : parseToMilliseconds(lowerTerm, context),
upperTerm == null ? null : parseToMilliseconds(upperTerm, context, includeUpper && parseUpperInclusive), upperTerm == null ? null : parseToMilliseconds(upperTerm, context, includeUpper),
includeLower, includeUpper); includeLower, includeUpper);
} }
@ -335,7 +343,7 @@ public class DateFieldMapper extends NumberFieldMapper<Long> {
public Filter rangeFilter(IndexFieldDataService fieldData, Object lowerTerm, Object upperTerm, boolean includeLower, boolean includeUpper, @Nullable QueryParseContext context) { public Filter rangeFilter(IndexFieldDataService fieldData, Object lowerTerm, Object upperTerm, boolean includeLower, boolean includeUpper, @Nullable QueryParseContext context) {
return NumericRangeFieldDataFilter.newLongRange((IndexNumericFieldData<?>) fieldData.getForField(this), return NumericRangeFieldDataFilter.newLongRange((IndexNumericFieldData<?>) fieldData.getForField(this),
lowerTerm == null ? null : parseToMilliseconds(lowerTerm, context), lowerTerm == null ? null : parseToMilliseconds(lowerTerm, context),
upperTerm == null ? null : parseToMilliseconds(upperTerm, context, includeUpper && parseUpperInclusive), upperTerm == null ? null : parseToMilliseconds(upperTerm, context, includeUpper),
includeLower, includeUpper); includeLower, includeUpper);
} }

View File

@ -99,11 +99,12 @@ public class TimestampFieldMapper extends DateFieldMapper implements InternalMap
@Override @Override
public TimestampFieldMapper build(BuilderContext context) { public TimestampFieldMapper build(BuilderContext context) {
boolean parseUpperInclusive = Defaults.PARSE_UPPER_INCLUSIVE; boolean roundCeil = Defaults.ROUND_CEIL;
if (context.indexSettings() != null) { if (context.indexSettings() != null) {
parseUpperInclusive = context.indexSettings().getAsBoolean("index.mapping.date.parse_upper_inclusive", Defaults.PARSE_UPPER_INCLUSIVE); Settings settings = context.indexSettings();
roundCeil = settings.getAsBoolean("index.mapping.date.round_ceil", settings.getAsBoolean("index.mapping.date.parse_upper_inclusive", Defaults.ROUND_CEIL));
} }
return new TimestampFieldMapper(fieldType, enabledState, path, dateTimeFormatter, parseUpperInclusive, return new TimestampFieldMapper(fieldType, enabledState, path, dateTimeFormatter, roundCeil,
ignoreMalformed(context), postingsProvider, docValuesProvider, fieldDataSettings, context.indexSettings()); ignoreMalformed(context), postingsProvider, docValuesProvider, fieldDataSettings, context.indexSettings());
} }
} }
@ -136,18 +137,18 @@ public class TimestampFieldMapper extends DateFieldMapper implements InternalMap
public TimestampFieldMapper() { public TimestampFieldMapper() {
this(new FieldType(Defaults.FIELD_TYPE), Defaults.ENABLED, Defaults.PATH, Defaults.DATE_TIME_FORMATTER, this(new FieldType(Defaults.FIELD_TYPE), Defaults.ENABLED, Defaults.PATH, Defaults.DATE_TIME_FORMATTER,
Defaults.PARSE_UPPER_INCLUSIVE, Defaults.IGNORE_MALFORMED, null, null, null, ImmutableSettings.EMPTY); Defaults.ROUND_CEIL, Defaults.IGNORE_MALFORMED, null, null, null, ImmutableSettings.EMPTY);
} }
protected TimestampFieldMapper(FieldType fieldType, EnabledAttributeMapper enabledState, String path, protected TimestampFieldMapper(FieldType fieldType, EnabledAttributeMapper enabledState, String path,
FormatDateTimeFormatter dateTimeFormatter, boolean parseUpperInclusive, FormatDateTimeFormatter dateTimeFormatter, boolean roundCeil,
Explicit<Boolean> ignoreMalformed, PostingsFormatProvider postingsProvider, Explicit<Boolean> ignoreMalformed, PostingsFormatProvider postingsProvider,
DocValuesFormatProvider docValuesProvider, @Nullable Settings fieldDataSettings, DocValuesFormatProvider docValuesProvider, @Nullable Settings fieldDataSettings,
Settings indexSettings) { Settings indexSettings) {
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.BOOST, fieldType, Defaults.PRECISION_STEP, Defaults.BOOST, fieldType,
Defaults.NULL_VALUE, TimeUnit.MILLISECONDS /*always milliseconds*/, Defaults.NULL_VALUE, TimeUnit.MILLISECONDS /*always milliseconds*/,
parseUpperInclusive, ignoreMalformed, postingsProvider, docValuesProvider, null, fieldDataSettings, indexSettings); roundCeil, ignoreMalformed, postingsProvider, docValuesProvider, null, fieldDataSettings, indexSettings);
this.enabledState = enabledState; this.enabledState = enabledState;
this.path = path; this.path = path;
} }

View File

@ -27,7 +27,7 @@ public class DateMathParserTests extends ElasticsearchTestCase {
assertThat(parser.parse("now+1m-1s", 0), equalTo(TimeUnit.MINUTES.toMillis(1) - TimeUnit.SECONDS.toMillis(1))); assertThat(parser.parse("now+1m-1s", 0), equalTo(TimeUnit.MINUTES.toMillis(1) - TimeUnit.SECONDS.toMillis(1)));
assertThat(parser.parse("now+1m+1s/m", 0), equalTo(TimeUnit.MINUTES.toMillis(1))); assertThat(parser.parse("now+1m+1s/m", 0), equalTo(TimeUnit.MINUTES.toMillis(1)));
assertThat(parser.parseUpperInclusive("now+1m+1s/m", 0), equalTo(TimeUnit.MINUTES.toMillis(2))); assertThat(parser.parseRoundCeil("now+1m+1s/m", 0), equalTo(TimeUnit.MINUTES.toMillis(2)));
assertThat(parser.parse("now+4y", 0), equalTo(TimeUnit.DAYS.toMillis(4*365 + 1))); assertThat(parser.parse("now+4y", 0), equalTo(TimeUnit.DAYS.toMillis(4*365 + 1)));
} }
@ -42,6 +42,6 @@ public class DateMathParserTests extends ElasticsearchTestCase {
assertThat(parser.parse("2013-01-01||+1y", 0), equalTo(parser.parse("2013-01-01", 0) + TimeUnit.DAYS.toMillis(365))); assertThat(parser.parse("2013-01-01||+1y", 0), equalTo(parser.parse("2013-01-01", 0) + TimeUnit.DAYS.toMillis(365)));
assertThat(parser.parse("2013-03-03||/y", 0), equalTo(parser.parse("2013-01-01", 0))); assertThat(parser.parse("2013-03-03||/y", 0), equalTo(parser.parse("2013-01-01", 0)));
assertThat(parser.parseUpperInclusive("2013-03-03||/y", 0), equalTo(parser.parse("2014-01-01", 0))); assertThat(parser.parseRoundCeil("2013-03-03||/y", 0), equalTo(parser.parse("2014-01-01", 0)));
} }
} }

View File

@ -130,7 +130,7 @@ public class SimpleSearchTests extends AbstractIntegrationTest {
@Test @Test
public void simpleDateRangeWithUpperInclusiveDisabledTests() throws Exception { public void simpleDateRangeWithUpperInclusiveDisabledTests() throws Exception {
prepareCreate("test").setSettings(ImmutableSettings.settingsBuilder().put("index.mapping.date.parse_upper_inclusive", false)).execute().actionGet(); prepareCreate("test").setSettings(ImmutableSettings.settingsBuilder().put("index.mapping.date.round_ceil", false)).execute().actionGet();
client().prepareIndex("test", "type1", "1").setSource("field", "2010-01-05T02:00").execute().actionGet(); client().prepareIndex("test", "type1", "1").setSource("field", "2010-01-05T02:00").execute().actionGet();
client().prepareIndex("test", "type1", "2").setSource("field", "2010-01-06T02:00").execute().actionGet(); client().prepareIndex("test", "type1", "2").setSource("field", "2010-01-06T02:00").execute().actionGet();
ensureGreen(); ensureGreen();