diff --git a/docs/CHANGELOG.asciidoc b/docs/CHANGELOG.asciidoc index 89b5f1fa3c26e..20368f4c77ffa 100644 --- a/docs/CHANGELOG.asciidoc +++ b/docs/CHANGELOG.asciidoc @@ -229,6 +229,12 @@ elasticsearch plugin. Engine:: * Harden periodically check to avoid endless flush loop {pull}29125[#29125] (issues: {issue}28350[#28350], {issue}29097[#29097]) +Use date format in `date_range` mapping before fallback to default ({pull}29310[#29310]) + +Fix NPE in 'more_like_this' when field has zero tokens ({pull}30365[#30365]) + +Fixed prerelease version of elasticsearch in the `deb` package to sort before GA versions +({pull}29000[#29000]) Ingest:: * 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]) Core:: * Remove special handling for _all in nodes info {pull}28971[#28971] (issue: {issue}28797[#28797]) +Use date format in `date_range` mapping before fallback to default ({pull}29310[#29310]) + +Fix NPE in 'more_like_this' when field has zero tokens ({pull}30365[#30365]) Engine:: * Avoid class cast exception from index writer {pull}28989[#28989] diff --git a/server/src/main/java/org/elasticsearch/index/mapper/RangeFieldMapper.java b/server/src/main/java/org/elasticsearch/index/mapper/RangeFieldMapper.java index 30f8b377f56d3..58fc9f88e6abb 100644 --- a/server/src/main/java/org/elasticsearch/index/mapper/RangeFieldMapper.java +++ b/server/src/main/java/org/elasticsearch/index/mapper/RangeFieldMapper.java @@ -315,6 +315,9 @@ public Query termQuery(Object value, QueryShardContext context) { public Query rangeQuery(Object lowerTerm, Object upperTerm, boolean includeLower, boolean includeUpper, ShapeRelation relation, DateTimeZone timeZone, DateMathParser parser, QueryShardContext context) { failIfNotIndexed(); + if (parser == null) { + parser = dateMathParser(); + } return rangeType.rangeQuery(name(), hasDocValues(), lowerTerm, upperTerm, includeLower, includeUpper, relation, timeZone, parser, context); } diff --git a/server/src/test/java/org/elasticsearch/index/mapper/RangeFieldTypeTests.java b/server/src/test/java/org/elasticsearch/index/mapper/RangeFieldTypeTests.java index 0c20153675af6..803ec60153d5e 100644 --- a/server/src/test/java/org/elasticsearch/index/mapper/RangeFieldTypeTests.java +++ b/server/src/test/java/org/elasticsearch/index/mapper/RangeFieldTypeTests.java @@ -19,7 +19,6 @@ package org.elasticsearch.index.mapper; -import com.carrotsearch.randomizedtesting.generators.RandomPicks; import org.apache.lucene.document.DoubleRange; import org.apache.lucene.document.FloatRange; import org.apache.lucene.document.InetAddressPoint; @@ -31,13 +30,16 @@ import org.apache.lucene.search.IndexOrDocValuesQuery; import org.apache.lucene.search.Query; import org.apache.lucene.util.BytesRef; +import org.elasticsearch.ElasticsearchParseException; import org.elasticsearch.Version; import org.elasticsearch.cluster.metadata.IndexMetaData; import org.elasticsearch.common.geo.ShapeRelation; +import org.elasticsearch.common.joda.FormatDateTimeFormatter; import org.elasticsearch.common.joda.Joda; import org.elasticsearch.common.network.InetAddresses; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.index.IndexSettings; +import org.elasticsearch.index.mapper.RangeFieldMapper.RangeFieldType; import org.elasticsearch.index.mapper.RangeFieldMapper.RangeType; import org.elasticsearch.index.query.QueryShardContext; import org.elasticsearch.test.IndexSettingsModule; @@ -55,42 +57,38 @@ public class RangeFieldTypeTests extends FieldTypeTestCase { @Before public void setupProperties() { - type = RandomPicks.randomFrom(random(), RangeType.values()); + type = randomFrom(RangeType.values()); nowInMillis = randomNonNegativeLong(); if (type == RangeType.DATE) { addModifier(new Modifier("format", true) { @Override public void modify(MappedFieldType ft) { - ((RangeFieldMapper.RangeFieldType) ft).setDateTimeFormatter(Joda.forPattern("basic_week_date", Locale.ROOT)); + ((RangeFieldType) ft).setDateTimeFormatter(Joda.forPattern("basic_week_date", Locale.ROOT)); } }); addModifier(new Modifier("locale", true) { @Override public void modify(MappedFieldType ft) { - ((RangeFieldMapper.RangeFieldType) ft).setDateTimeFormatter(Joda.forPattern("date_optional_time", Locale.CANADA)); + ((RangeFieldType) ft).setDateTimeFormatter(Joda.forPattern("date_optional_time", Locale.CANADA)); } }); } } @Override - protected RangeFieldMapper.RangeFieldType createDefaultFieldType() { - return new RangeFieldMapper.RangeFieldType(type, Version.CURRENT); + protected RangeFieldType createDefaultFieldType() { + return new RangeFieldType(type, Version.CURRENT); } public void testRangeQuery() throws Exception { - Settings indexSettings = Settings.builder() - .put(IndexMetaData.SETTING_VERSION_CREATED, Version.CURRENT).build(); - IndexSettings idxSettings = IndexSettingsModule.newIndexSettings(randomAlphaOfLengthBetween(1, 10), indexSettings); - QueryShardContext context = new QueryShardContext(0, idxSettings, null, null, null, null, null, xContentRegistry(), - writableRegistry(), null, null, () -> nowInMillis, null); - RangeFieldMapper.RangeFieldType ft = new RangeFieldMapper.RangeFieldType(type, Version.CURRENT); + QueryShardContext context = createContext(); + RangeFieldType ft = new RangeFieldType(type, Version.CURRENT); ft.setName(FIELDNAME); ft.setIndexOptions(IndexOptions.DOCS); - ShapeRelation relation = RandomPicks.randomFrom(random(), ShapeRelation.values()); - boolean includeLower = random().nextBoolean(); - boolean includeUpper = random().nextBoolean(); + ShapeRelation relation = randomFrom(ShapeRelation.values()); + boolean includeLower = randomBoolean(); + boolean includeUpper = randomBoolean(); Object from = nextFrom(); Object to = nextTo(from); @@ -98,6 +96,41 @@ public void testRangeQuery() throws Exception { ft.rangeQuery(from, to, includeLower, includeUpper, relation, null, null, context)); } + private QueryShardContext createContext() { + Settings indexSettings = Settings.builder() + .put(IndexMetaData.SETTING_VERSION_CREATED, Version.CURRENT).build(); + IndexSettings idxSettings = IndexSettingsModule.newIndexSettings(randomAlphaOfLengthBetween(1, 10), indexSettings); + return new QueryShardContext(0, idxSettings, null, null, null, null, null, xContentRegistry(), + writableRegistry(), null, null, () -> nowInMillis, null); + } + + public void testDateRangeQueryUsingMappingFormat() { + QueryShardContext context = createContext(); + RangeFieldType fieldType = new RangeFieldType(RangeType.DATE, Version.CURRENT); + fieldType.setName(FIELDNAME); + fieldType.setIndexOptions(IndexOptions.DOCS); + fieldType.setHasDocValues(false); + ShapeRelation relation = randomFrom(ShapeRelation.values()); + + // dates will break the default format + final String from = "2016-15-06T15:29:50+08:00"; + final String to = "2016-16-06T15:29:50+08:00"; + + ElasticsearchParseException ex = expectThrows(ElasticsearchParseException.class, + () -> fieldType.rangeQuery(from, to, true, true, relation, null, null, context)); + assertEquals("failed to parse date field [2016-15-06T15:29:50+08:00] with format [strict_date_optional_time||epoch_millis]", + ex.getMessage()); + + // setting mapping format which is compatible with those dates + final FormatDateTimeFormatter formatter = Joda.forPattern("yyyy-dd-MM'T'HH:mm:ssZZ"); + assertEquals(1465975790000L, formatter.parser().parseMillis(from)); + assertEquals(1466062190000L, formatter.parser().parseMillis(to)); + + fieldType.setDateTimeFormatter(formatter); + final Query query = fieldType.rangeQuery(from, to, true, true, relation, null, null, context); + assertEquals("field:", query.toString()); + } + private Query getExpectedRangeQuery(ShapeRelation relation, Object from, Object to, boolean includeLower, boolean includeUpper) { switch (type) { case DATE: @@ -277,14 +310,10 @@ public void testParseIp() { assertEquals(InetAddresses.forString("::1"), RangeFieldMapper.RangeType.IP.parse(new BytesRef("::1"), randomBoolean())); } - public void testTermQuery() throws Exception, IllegalArgumentException { + public void testTermQuery() throws Exception { // See https://github.com/elastic/elasticsearch/issues/25950 - Settings indexSettings = Settings.builder() - .put(IndexMetaData.SETTING_VERSION_CREATED, Version.CURRENT).build(); - IndexSettings idxSettings = IndexSettingsModule.newIndexSettings(randomAlphaOfLengthBetween(1, 10), indexSettings); - QueryShardContext context = new QueryShardContext(0, idxSettings, null, null, null, null, null, xContentRegistry(), - writableRegistry(), null, null, () -> nowInMillis, null); - RangeFieldMapper.RangeFieldType ft = new RangeFieldMapper.RangeFieldType(type, Version.CURRENT); + QueryShardContext context = createContext(); + RangeFieldType ft = new RangeFieldType(type, Version.CURRENT); ft.setName(FIELDNAME); ft.setIndexOptions(IndexOptions.DOCS);