Skip to content

Commit 8a8ad1b

Browse files
authored
updated rangetype to be more inline with the docs (https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-range-query.html) and added tests to reflect as much (#113872)
1 parent bb0a9f4 commit 8a8ad1b

File tree

7 files changed

+225
-4
lines changed

7 files changed

+225
-4
lines changed

docs/reference/mapping/types/range.asciidoc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -465,7 +465,7 @@ Will become:
465465
},
466466
{
467467
"gte": "2017-09-01T00:00:00.000Z",
468-
"lte": "2017-09-10T00:00:00.000Z"
468+
"lte": "2017-09-10T23:59:59.999Z"
469469
}
470470
]
471471
}

rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/range/10_basic.yml

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -446,6 +446,77 @@ setup:
446446

447447
- match: { hits.total: 2 }
448448

449+
---
450+
"Date range edge cases":
451+
- requires:
452+
cluster_features: ["mapper.range.date_range_indexing_fix"]
453+
reason: "tests rounding fixes in 8.16.0 that previously caused non-intuitive indexing and query because ranges were assumed to always index with 0's as the default such as when time is missing 00:00:00.000 time was assumed but for lte indexing and query missing time should be 23:59:59.999 as per docs here: https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-range-query.html"
454+
455+
- do:
456+
indices.create:
457+
index: test_date_range_edge_cases
458+
body:
459+
mappings:
460+
"properties":
461+
"date_range":
462+
"type": "date_range"
463+
"format": "yyyy-MM-dd"
464+
465+
- do:
466+
index:
467+
index: test_date_range_edge_cases
468+
id: "1"
469+
body: { "date_range": { "gte": "1980-12-14", "lte": "1980-12-17" } }
470+
471+
- do:
472+
index:
473+
index: test_date_range_edge_cases
474+
id: "2"
475+
body: { "date_range": { "gt": "1990-12-15", "lt": "1990-12-18" } }
476+
477+
- do:
478+
index:
479+
index: test_date_range_edge_cases
480+
id: "3"
481+
body: { "date_range": { "gte": "1985-12-16||/M", "lte": "1986-02-10||/M" } }
482+
483+
- do:
484+
index:
485+
index: test_date_range_edge_cases
486+
id: "4"
487+
body: { "date_range": { "gt": "1995-12-16||/M", "lt": "1996-02-10||/M" } }
488+
489+
- do:
490+
indices.refresh: { }
491+
492+
- do:
493+
search:
494+
rest_total_hits_as_int: true
495+
body: { "size": 0, "query": { "range": { "date_range": { "gte": "1980-12-14", "lte": "1980-12-17", "relation": "contains" } } } }
496+
497+
- match: { hits.total: 1 }
498+
499+
- do:
500+
search:
501+
rest_total_hits_as_int: true
502+
body: { "size": 0, "query": { "range": { "date_range": { "gt": "1990-12-15", "lt": "1990-12-18", "relation": "contains" } } } }
503+
504+
- match: { hits.total: 1 }
505+
506+
- do:
507+
search:
508+
rest_total_hits_as_int: true
509+
body: { "size": 0, "query": { "range": { "date_range": { "gte": "1985-12-16||/M", "lte": "1986-02-10||/M", "relation": "contains" } } } }
510+
511+
- match: { hits.total: 1 }
512+
513+
- do:
514+
search:
515+
rest_total_hits_as_int: true
516+
body: { "size": 0, "query": { "range": { "date_range": { "gt": "1995-12-16||/M", "lt": "1996-02-10||/M", "relation": "contains" } } } }
517+
518+
- match: { hits.total: 1 }
519+
449520
---
450521
"Null bounds":
451522

rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/range/20_synthetic_source.yml

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -527,6 +527,9 @@ setup:
527527

528528
---
529529
"Date range":
530+
- skip:
531+
cluster_features: ["mapper.range.date_range_indexing_fix"]
532+
reason: "tests prior to rounding fixes in 8.16.0 that caused non-intuitive indexing and query because ranges were assumed to always index with 0's as the default such as when time is missing 00:00:00.000 time was assumed but for lte indexing and query missing time should be 23:59:59.999 as per docs here: https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-range-query.html"
530533

531534
- do:
532535
index:
@@ -655,3 +658,137 @@ setup:
655658
- match:
656659
_source:
657660
date_range: { "gte": "2017-09-05T00:00:00.000Z", "lte": null }
661+
662+
---
663+
"Date range Rounding Fixes":
664+
- requires:
665+
cluster_features: ["mapper.range.date_range_indexing_fix"]
666+
reason: "tests rounding fixes in 8.16.0 that previously caused non-intuitive indexing and query because ranges were assumed to always index with 0's as the default such as when time is missing 00:00:00.000 time was assumed but for lte indexing and query missing time should be 23:59:59.999 as per docs here: https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-range-query.html"
667+
668+
- do:
669+
index:
670+
index: synthetic_source_test
671+
id: "1"
672+
body: { "date_range": { "gte": "2017-09-01", "lte": "2017-09-05" } }
673+
674+
- do:
675+
index:
676+
index: synthetic_source_test
677+
id: "2"
678+
body: { "date_range": { "gt": "2017-09-01", "lte": "2017-09-03" } }
679+
680+
- do:
681+
index:
682+
index: synthetic_source_test
683+
id: "3"
684+
body: { "date_range": [ { "gte": "2017-09-04", "lt": "2017-09-05" } ] }
685+
686+
- do:
687+
index:
688+
index: synthetic_source_test
689+
id: "4"
690+
body: { "date_range": [ { "gt": "2017-09-04", "lt": "2017-09-08" }, { "gt": "2017-09-04", "lt": "2017-09-07" } ] }
691+
692+
- do:
693+
index:
694+
index: synthetic_source_test
695+
id: "5"
696+
body: { "date_range": { "gte": 1504224000000, "lte": 1504569600000 } }
697+
698+
- do:
699+
index:
700+
index: synthetic_source_test
701+
id: "6"
702+
body: { "date_range": { "gte": "2017-09-01T10:20:30.123Z", "lte": "2017-09-05T03:04:05.789Z" } }
703+
704+
- do:
705+
index:
706+
index: synthetic_source_test
707+
id: "7"
708+
body: { "date_range": null }
709+
710+
- do:
711+
index:
712+
index: synthetic_source_test
713+
id: "8"
714+
body: { "date_range": { "gte": null, "lte": "2017-09-05" } }
715+
716+
- do:
717+
index:
718+
index: synthetic_source_test
719+
id: "9"
720+
body: { "date_range": { "gte": "2017-09-05" } }
721+
722+
- do:
723+
indices.refresh: { }
724+
725+
- do:
726+
get:
727+
index: synthetic_source_test
728+
id: "1"
729+
- match:
730+
_source:
731+
date_range: { "gte": "2017-09-01T00:00:00.000Z", "lte": "2017-09-05T23:59:59.999Z" }
732+
733+
- do:
734+
get:
735+
index: synthetic_source_test
736+
id: "2"
737+
- match:
738+
_source:
739+
date_range: { "gte": "2017-09-02T00:00:00.000Z", "lte": "2017-09-03T23:59:59.999Z" }
740+
741+
- do:
742+
get:
743+
index: synthetic_source_test
744+
id: "3"
745+
- match:
746+
_source:
747+
date_range: { "gte": "2017-09-04T00:00:00.000Z", "lte": "2017-09-04T23:59:59.999Z" }
748+
749+
- do:
750+
get:
751+
index: synthetic_source_test
752+
id: "4"
753+
- match:
754+
_source:
755+
date_range: [ { "gte": "2017-09-05T00:00:00.000Z", "lte": "2017-09-06T23:59:59.999Z" }, { "gte": "2017-09-05T00:00:00.000Z", "lte": "2017-09-07T23:59:59.999Z" } ]
756+
757+
- do:
758+
get:
759+
index: synthetic_source_test
760+
id: "5"
761+
- match:
762+
_source:
763+
date_range: { "gte": "2017-09-01T00:00:00.000Z", "lte": "2017-09-05T00:00:00.000Z" }
764+
765+
- do:
766+
get:
767+
index: synthetic_source_test
768+
id: "6"
769+
- match:
770+
_source:
771+
date_range: { "gte": "2017-09-01T10:20:30.123Z", "lte": "2017-09-05T03:04:05.789Z" }
772+
773+
- do:
774+
get:
775+
index: synthetic_source_test
776+
id: "7"
777+
- match:
778+
_source: { }
779+
780+
- do:
781+
get:
782+
index: synthetic_source_test
783+
id: "8"
784+
- match:
785+
_source:
786+
date_range: { "gte": null, "lte": "2017-09-05T23:59:59.999Z" }
787+
788+
- do:
789+
get:
790+
index: synthetic_source_test
791+
id: "9"
792+
- match:
793+
_source:
794+
date_range: { "gte": "2017-09-05T00:00:00.000Z", "lte": null }

server/src/main/java/org/elasticsearch/index/mapper/MapperFeatures.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,4 +49,9 @@ public Set<NodeFeature> getFeatures() {
4949
FlattenedFieldMapper.IGNORE_ABOVE_WITH_ARRAYS_SUPPORT
5050
);
5151
}
52+
53+
@Override
54+
public Set<NodeFeature> getTestFeatures() {
55+
return Set.of(RangeFieldMapper.DATE_RANGE_INDEXING_FIX);
56+
}
5257
}

server/src/main/java/org/elasticsearch/index/mapper/RangeFieldMapper.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@
5252
/** A {@link FieldMapper} for indexing numeric and date ranges, and creating queries */
5353
public class RangeFieldMapper extends FieldMapper {
5454
public static final NodeFeature NULL_VALUES_OFF_BY_ONE_FIX = new NodeFeature("mapper.range.null_values_off_by_one_fix");
55+
public static final NodeFeature DATE_RANGE_INDEXING_FIX = new NodeFeature("mapper.range.date_range_indexing_fix");
5556

5657
public static final boolean DEFAULT_INCLUDE_UPPER = true;
5758
public static final boolean DEFAULT_INCLUDE_LOWER = true;

server/src/main/java/org/elasticsearch/index/mapper/RangeType.java

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -196,14 +196,20 @@ public Field getRangeField(String name, RangeFieldMapper.Range r) {
196196
@Override
197197
public Number parseFrom(RangeFieldMapper.RangeFieldType fieldType, XContentParser parser, boolean coerce, boolean included)
198198
throws IOException {
199-
Number value = parseValue(parser.text(), coerce, fieldType.dateMathParser);
199+
assert fieldType.dateMathParser != null;
200+
Number value = fieldType.dateMathParser.parse(parser.text(), () -> {
201+
throw new IllegalArgumentException("now is not used at indexing time");
202+
}, included == false, null).toEpochMilli();
200203
return included ? value : nextUp(value);
201204
}
202205

203206
@Override
204207
public Number parseTo(RangeFieldMapper.RangeFieldType fieldType, XContentParser parser, boolean coerce, boolean included)
205208
throws IOException {
206-
Number value = parseValue(parser.text(), coerce, fieldType.dateMathParser);
209+
assert fieldType.dateMathParser != null;
210+
Number value = fieldType.dateMathParser.parse(parser.text(), () -> {
211+
throw new IllegalArgumentException("now is not used at indexing time");
212+
}, included, null).toEpochMilli();
207213
return included ? value : nextDown(value);
208214
}
209215

@@ -295,6 +301,7 @@ public Query rangeQuery(
295301
roundUp,
296302
zone
297303
).toEpochMilli();
304+
298305
roundUp = includeUpper; // using "lte" should round upper bound up
299306
Long high = upperTerm == null
300307
? maxValue()

server/src/test/java/org/elasticsearch/index/mapper/DateRangeFieldMapperTests.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ protected XContentBuilder rangeSource(XContentBuilder in) throws IOException {
3333

3434
@Override
3535
protected String storedValue() {
36-
return "1477872000000";
36+
return "1477958399999";
3737
}
3838

3939
@Override

0 commit comments

Comments
 (0)