Skip to content

Commit 5ec9041

Browse files
Ke LiChristoph Büscher
Ke Li
authored and
Christoph Büscher
committed
Use date format in date_range mapping before fallback to default (#29310)
If the date format is not forced in query, use the format in mapping before fallback to the default format. Closes #29282
1 parent 28cc588 commit 5ec9041

File tree

3 files changed

+63
-22
lines changed

3 files changed

+63
-22
lines changed

docs/CHANGELOG.asciidoc

+9
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,12 @@ elasticsearch plugin.
229229

230230
Engine::
231231
* Harden periodically check to avoid endless flush loop {pull}29125[#29125] (issues: {issue}28350[#28350], {issue}29097[#29097])
232+
Use date format in `date_range` mapping before fallback to default ({pull}29310[#29310])
233+
234+
Fix NPE in 'more_like_this' when field has zero tokens ({pull}30365[#30365])
235+
236+
Fixed prerelease version of elasticsearch in the `deb` package to sort before GA versions
237+
({pull}29000[#29000])
232238

233239
Ingest::
234240
* Don't allow referencing the pattern bank name in the pattern bank {pull}29295[#29295] (issue: {issue}29257[#29257])
@@ -336,6 +342,9 @@ Added put index template API to the high level rest client ({pull}30400[#30400])
336342

337343
Core::
338344
* Remove special handling for _all in nodes info {pull}28971[#28971] (issue: {issue}28797[#28797])
345+
Use date format in `date_range` mapping before fallback to default ({pull}29310[#29310])
346+
347+
Fix NPE in 'more_like_this' when field has zero tokens ({pull}30365[#30365])
339348

340349
Engine::
341350
* Avoid class cast exception from index writer {pull}28989[#28989]

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

+3
Original file line numberDiff line numberDiff line change
@@ -315,6 +315,9 @@ public Query termQuery(Object value, QueryShardContext context) {
315315
public Query rangeQuery(Object lowerTerm, Object upperTerm, boolean includeLower, boolean includeUpper,
316316
ShapeRelation relation, DateTimeZone timeZone, DateMathParser parser, QueryShardContext context) {
317317
failIfNotIndexed();
318+
if (parser == null) {
319+
parser = dateMathParser();
320+
}
318321
return rangeType.rangeQuery(name(), hasDocValues(), lowerTerm, upperTerm, includeLower, includeUpper, relation,
319322
timeZone, parser, context);
320323
}

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

+51-22
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919

2020
package org.elasticsearch.index.mapper;
2121

22-
import com.carrotsearch.randomizedtesting.generators.RandomPicks;
2322
import org.apache.lucene.document.DoubleRange;
2423
import org.apache.lucene.document.FloatRange;
2524
import org.apache.lucene.document.InetAddressPoint;
@@ -31,13 +30,16 @@
3130
import org.apache.lucene.search.IndexOrDocValuesQuery;
3231
import org.apache.lucene.search.Query;
3332
import org.apache.lucene.util.BytesRef;
33+
import org.elasticsearch.ElasticsearchParseException;
3434
import org.elasticsearch.Version;
3535
import org.elasticsearch.cluster.metadata.IndexMetaData;
3636
import org.elasticsearch.common.geo.ShapeRelation;
37+
import org.elasticsearch.common.joda.FormatDateTimeFormatter;
3738
import org.elasticsearch.common.joda.Joda;
3839
import org.elasticsearch.common.network.InetAddresses;
3940
import org.elasticsearch.common.settings.Settings;
4041
import org.elasticsearch.index.IndexSettings;
42+
import org.elasticsearch.index.mapper.RangeFieldMapper.RangeFieldType;
4143
import org.elasticsearch.index.mapper.RangeFieldMapper.RangeType;
4244
import org.elasticsearch.index.query.QueryShardContext;
4345
import org.elasticsearch.test.IndexSettingsModule;
@@ -55,49 +57,80 @@ public class RangeFieldTypeTests extends FieldTypeTestCase {
5557

5658
@Before
5759
public void setupProperties() {
58-
type = RandomPicks.randomFrom(random(), RangeType.values());
60+
type = randomFrom(RangeType.values());
5961
nowInMillis = randomNonNegativeLong();
6062
if (type == RangeType.DATE) {
6163
addModifier(new Modifier("format", true) {
6264
@Override
6365
public void modify(MappedFieldType ft) {
64-
((RangeFieldMapper.RangeFieldType) ft).setDateTimeFormatter(Joda.forPattern("basic_week_date", Locale.ROOT));
66+
((RangeFieldType) ft).setDateTimeFormatter(Joda.forPattern("basic_week_date", Locale.ROOT));
6567
}
6668
});
6769
addModifier(new Modifier("locale", true) {
6870
@Override
6971
public void modify(MappedFieldType ft) {
70-
((RangeFieldMapper.RangeFieldType) ft).setDateTimeFormatter(Joda.forPattern("date_optional_time", Locale.CANADA));
72+
((RangeFieldType) ft).setDateTimeFormatter(Joda.forPattern("date_optional_time", Locale.CANADA));
7173
}
7274
});
7375
}
7476
}
7577

7678
@Override
77-
protected RangeFieldMapper.RangeFieldType createDefaultFieldType() {
78-
return new RangeFieldMapper.RangeFieldType(type, Version.CURRENT);
79+
protected RangeFieldType createDefaultFieldType() {
80+
return new RangeFieldType(type, Version.CURRENT);
7981
}
8082

8183
public void testRangeQuery() throws Exception {
82-
Settings indexSettings = Settings.builder()
83-
.put(IndexMetaData.SETTING_VERSION_CREATED, Version.CURRENT).build();
84-
IndexSettings idxSettings = IndexSettingsModule.newIndexSettings(randomAlphaOfLengthBetween(1, 10), indexSettings);
85-
QueryShardContext context = new QueryShardContext(0, idxSettings, null, null, null, null, null, xContentRegistry(),
86-
writableRegistry(), null, null, () -> nowInMillis, null);
87-
RangeFieldMapper.RangeFieldType ft = new RangeFieldMapper.RangeFieldType(type, Version.CURRENT);
84+
QueryShardContext context = createContext();
85+
RangeFieldType ft = new RangeFieldType(type, Version.CURRENT);
8886
ft.setName(FIELDNAME);
8987
ft.setIndexOptions(IndexOptions.DOCS);
9088

91-
ShapeRelation relation = RandomPicks.randomFrom(random(), ShapeRelation.values());
92-
boolean includeLower = random().nextBoolean();
93-
boolean includeUpper = random().nextBoolean();
89+
ShapeRelation relation = randomFrom(ShapeRelation.values());
90+
boolean includeLower = randomBoolean();
91+
boolean includeUpper = randomBoolean();
9492
Object from = nextFrom();
9593
Object to = nextTo(from);
9694

9795
assertEquals(getExpectedRangeQuery(relation, from, to, includeLower, includeUpper),
9896
ft.rangeQuery(from, to, includeLower, includeUpper, relation, null, null, context));
9997
}
10098

99+
private QueryShardContext createContext() {
100+
Settings indexSettings = Settings.builder()
101+
.put(IndexMetaData.SETTING_VERSION_CREATED, Version.CURRENT).build();
102+
IndexSettings idxSettings = IndexSettingsModule.newIndexSettings(randomAlphaOfLengthBetween(1, 10), indexSettings);
103+
return new QueryShardContext(0, idxSettings, null, null, null, null, null, xContentRegistry(),
104+
writableRegistry(), null, null, () -> nowInMillis, null);
105+
}
106+
107+
public void testDateRangeQueryUsingMappingFormat() {
108+
QueryShardContext context = createContext();
109+
RangeFieldType fieldType = new RangeFieldType(RangeType.DATE, Version.CURRENT);
110+
fieldType.setName(FIELDNAME);
111+
fieldType.setIndexOptions(IndexOptions.DOCS);
112+
fieldType.setHasDocValues(false);
113+
ShapeRelation relation = randomFrom(ShapeRelation.values());
114+
115+
// dates will break the default format
116+
final String from = "2016-15-06T15:29:50+08:00";
117+
final String to = "2016-16-06T15:29:50+08:00";
118+
119+
ElasticsearchParseException ex = expectThrows(ElasticsearchParseException.class,
120+
() -> fieldType.rangeQuery(from, to, true, true, relation, null, null, context));
121+
assertEquals("failed to parse date field [2016-15-06T15:29:50+08:00] with format [strict_date_optional_time||epoch_millis]",
122+
ex.getMessage());
123+
124+
// setting mapping format which is compatible with those dates
125+
final FormatDateTimeFormatter formatter = Joda.forPattern("yyyy-dd-MM'T'HH:mm:ssZZ");
126+
assertEquals(1465975790000L, formatter.parser().parseMillis(from));
127+
assertEquals(1466062190000L, formatter.parser().parseMillis(to));
128+
129+
fieldType.setDateTimeFormatter(formatter);
130+
final Query query = fieldType.rangeQuery(from, to, true, true, relation, null, null, context);
131+
assertEquals("field:<ranges:[1465975790000 : 1466062190000]>", query.toString());
132+
}
133+
101134
private Query getExpectedRangeQuery(ShapeRelation relation, Object from, Object to, boolean includeLower, boolean includeUpper) {
102135
switch (type) {
103136
case DATE:
@@ -277,14 +310,10 @@ public void testParseIp() {
277310
assertEquals(InetAddresses.forString("::1"), RangeFieldMapper.RangeType.IP.parse(new BytesRef("::1"), randomBoolean()));
278311
}
279312

280-
public void testTermQuery() throws Exception, IllegalArgumentException {
313+
public void testTermQuery() throws Exception {
281314
// See https://github.com/elastic/elasticsearch/issues/25950
282-
Settings indexSettings = Settings.builder()
283-
.put(IndexMetaData.SETTING_VERSION_CREATED, Version.CURRENT).build();
284-
IndexSettings idxSettings = IndexSettingsModule.newIndexSettings(randomAlphaOfLengthBetween(1, 10), indexSettings);
285-
QueryShardContext context = new QueryShardContext(0, idxSettings, null, null, null, null, null, xContentRegistry(),
286-
writableRegistry(), null, null, () -> nowInMillis, null);
287-
RangeFieldMapper.RangeFieldType ft = new RangeFieldMapper.RangeFieldType(type, Version.CURRENT);
315+
QueryShardContext context = createContext();
316+
RangeFieldType ft = new RangeFieldType(type, Version.CURRENT);
288317
ft.setName(FIELDNAME);
289318
ft.setIndexOptions(IndexOptions.DOCS);
290319

0 commit comments

Comments
 (0)