From c9dab6991eff5c01c7b0c36aecaf0f061267e030 Mon Sep 17 00:00:00 2001 From: Britta Weber Date: Tue, 15 Oct 2013 17:28:35 +0200 Subject: [PATCH] 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 --- docs/reference/mapping/date-format.asciidoc | 4 +++ .../common/joda/DateMathParser.java | 16 +++++----- .../index/mapper/core/DateFieldMapper.java | 30 ++++++++++++------- .../mapper/internal/TimestampFieldMapper.java | 13 ++++---- .../common/joda/DateMathParserTests.java | 4 +-- .../search/simple/SimpleSearchTests.java | 2 +- 6 files changed, 41 insertions(+), 28 deletions(-) diff --git a/docs/reference/mapping/date-format.asciidoc b/docs/reference/mapping/date-format.asciidoc index 5a03c460a46..0f43764ab6f 100644 --- a/docs/reference/mapping/date-format.asciidoc +++ b/docs/reference/mapping/date-format.asciidoc @@ -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 of flooring it. +To change this behavior, set +`"mapping.date.round_ceil": false`. + + [float] [[built-in]] === Built In Formats diff --git a/src/main/java/org/elasticsearch/common/joda/DateMathParser.java b/src/main/java/org/elasticsearch/common/joda/DateMathParser.java index 760f69c9de4..3e9fec38e59 100644 --- a/src/main/java/org/elasticsearch/common/joda/DateMathParser.java +++ b/src/main/java/org/elasticsearch/common/joda/DateMathParser.java @@ -20,14 +20,14 @@ public class DateMathParser { } 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) { - return parse(text, now, true, true); + public long parseRoundCeil(String text, long now) { + 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; String mathString; if (text.startsWith("now")) { @@ -43,8 +43,8 @@ public class DateMathParser { parseString = text.substring(0, index); mathString = text.substring(index + 2); } - if (upperInclusive) { - time = parseUpperInclusiveStringValue(parseString); + if (roundCeil) { + time = parseRoundCeilStringValue(parseString); } else { time = parseStringValue(parseString); } @@ -54,7 +54,7 @@ public class DateMathParser { return time; } - return parseMath(mathString, time, roundUp); + return parseMath(mathString, time, roundCeil); } 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 { // 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. diff --git a/src/main/java/org/elasticsearch/index/mapper/core/DateFieldMapper.java b/src/main/java/org/elasticsearch/index/mapper/core/DateFieldMapper.java index 8736c0696a1..5b41a12904d 100644 --- a/src/main/java/org/elasticsearch/index/mapper/core/DateFieldMapper.java +++ b/src/main/java/org/elasticsearch/index/mapper/core/DateFieldMapper.java @@ -81,7 +81,7 @@ public class DateFieldMapper extends NumberFieldMapper { public static final String NULL_VALUE = null; 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 { @@ -118,16 +118,17 @@ public class DateFieldMapper extends NumberFieldMapper { @Override public DateFieldMapper build(BuilderContext context) { - boolean parseUpperInclusive = Defaults.PARSE_UPPER_INCLUSIVE; + boolean roundCeil = Defaults.ROUND_CEIL; 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); if (!locale.equals(dateTimeFormatter.locale())) { dateTimeFormatter = new FormatDateTimeFormatter(dateTimeFormatter.format(), dateTimeFormatter.parser(), dateTimeFormatter.printer(), locale); } 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()); fieldMapper.includeInAll(includeInAll); return fieldMapper; @@ -184,7 +185,14 @@ public class DateFieldMapper extends NumberFieldMapper { 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; @@ -193,7 +201,7 @@ public class DateFieldMapper extends NumberFieldMapper { protected final TimeUnit timeUnit; protected DateFieldMapper(Names names, FormatDateTimeFormatter dateTimeFormatter, int precisionStep, float boost, FieldType fieldType, - String nullValue, TimeUnit timeUnit, boolean parseUpperInclusive, Explicit ignoreMalformed, + String nullValue, TimeUnit timeUnit, boolean roundCeil, Explicit ignoreMalformed, PostingsFormatProvider postingsProvider, DocValuesFormatProvider docValuesProvider, SimilarityProvider similarity, @Nullable Settings fieldDataSettings, Settings indexSettings) { super(names, precisionStep, boost, fieldType, ignoreMalformed, new NamedAnalyzer("_date/" + precisionStep, @@ -203,7 +211,7 @@ public class DateFieldMapper extends NumberFieldMapper { this.dateTimeFormatter = dateTimeFormatter; this.nullValue = nullValue; this.timeUnit = timeUnit; - this.parseUpperInclusive = parseUpperInclusive; + this.roundCeil = roundCeil; this.dateMathParser = new DateMathParser(dateTimeFormatter, timeUnit); } @@ -305,7 +313,7 @@ public class DateFieldMapper extends NumberFieldMapper { public long parseToMilliseconds(Object value, @Nullable QueryParseContext context, boolean includeUpper) { 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 @@ -319,7 +327,7 @@ public class DateFieldMapper extends NumberFieldMapper { public Query rangeQuery(Object lowerTerm, Object upperTerm, boolean includeLower, boolean includeUpper, @Nullable QueryParseContext context) { return NumericRangeQuery.newLongRange(names.indexName(), precisionStep, lowerTerm == null ? null : parseToMilliseconds(lowerTerm, context), - upperTerm == null ? null : parseToMilliseconds(upperTerm, context, includeUpper && parseUpperInclusive), + upperTerm == null ? null : parseToMilliseconds(upperTerm, context, includeUpper), includeLower, includeUpper); } @@ -327,7 +335,7 @@ public class DateFieldMapper extends NumberFieldMapper { public Filter rangeFilter(Object lowerTerm, Object upperTerm, boolean includeLower, boolean includeUpper, @Nullable QueryParseContext context) { return NumericRangeFilter.newLongRange(names.indexName(), precisionStep, lowerTerm == null ? null : parseToMilliseconds(lowerTerm, context), - upperTerm == null ? null : parseToMilliseconds(upperTerm, context, includeUpper && parseUpperInclusive), + upperTerm == null ? null : parseToMilliseconds(upperTerm, context, includeUpper), includeLower, includeUpper); } @@ -335,7 +343,7 @@ public class DateFieldMapper extends NumberFieldMapper { public Filter rangeFilter(IndexFieldDataService fieldData, Object lowerTerm, Object upperTerm, boolean includeLower, boolean includeUpper, @Nullable QueryParseContext context) { return NumericRangeFieldDataFilter.newLongRange((IndexNumericFieldData) fieldData.getForField(this), lowerTerm == null ? null : parseToMilliseconds(lowerTerm, context), - upperTerm == null ? null : parseToMilliseconds(upperTerm, context, includeUpper && parseUpperInclusive), + upperTerm == null ? null : parseToMilliseconds(upperTerm, context, includeUpper), includeLower, includeUpper); } diff --git a/src/main/java/org/elasticsearch/index/mapper/internal/TimestampFieldMapper.java b/src/main/java/org/elasticsearch/index/mapper/internal/TimestampFieldMapper.java index 35002c1701f..1e1e4b41974 100644 --- a/src/main/java/org/elasticsearch/index/mapper/internal/TimestampFieldMapper.java +++ b/src/main/java/org/elasticsearch/index/mapper/internal/TimestampFieldMapper.java @@ -99,11 +99,12 @@ public class TimestampFieldMapper extends DateFieldMapper implements InternalMap @Override public TimestampFieldMapper build(BuilderContext context) { - boolean parseUpperInclusive = Defaults.PARSE_UPPER_INCLUSIVE; + boolean roundCeil = Defaults.ROUND_CEIL; 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()); } } @@ -136,18 +137,18 @@ public class TimestampFieldMapper extends DateFieldMapper implements InternalMap public TimestampFieldMapper() { 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, - FormatDateTimeFormatter dateTimeFormatter, boolean parseUpperInclusive, + FormatDateTimeFormatter dateTimeFormatter, boolean roundCeil, Explicit ignoreMalformed, PostingsFormatProvider postingsProvider, DocValuesFormatProvider docValuesProvider, @Nullable Settings fieldDataSettings, Settings indexSettings) { super(new Names(Defaults.NAME, Defaults.NAME, Defaults.NAME, Defaults.NAME), dateTimeFormatter, Defaults.PRECISION_STEP, Defaults.BOOST, fieldType, 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.path = path; } diff --git a/src/test/java/org/elasticsearch/common/joda/DateMathParserTests.java b/src/test/java/org/elasticsearch/common/joda/DateMathParserTests.java index f472c401067..0a0418a16d3 100644 --- a/src/test/java/org/elasticsearch/common/joda/DateMathParserTests.java +++ b/src/test/java/org/elasticsearch/common/joda/DateMathParserTests.java @@ -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/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))); } @@ -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-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))); } } diff --git a/src/test/java/org/elasticsearch/search/simple/SimpleSearchTests.java b/src/test/java/org/elasticsearch/search/simple/SimpleSearchTests.java index 7f544c9d78f..ebed7289586 100644 --- a/src/test/java/org/elasticsearch/search/simple/SimpleSearchTests.java +++ b/src/test/java/org/elasticsearch/search/simple/SimpleSearchTests.java @@ -130,7 +130,7 @@ public class SimpleSearchTests extends AbstractIntegrationTest { @Test 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", "2").setSource("field", "2010-01-06T02:00").execute().actionGet(); ensureGreen();