Skip to content

Use date format in date_range mapping before fallback to default #29310

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
May 9, 2018
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,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);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,13 @@
import org.elasticsearch.Version;
import org.elasticsearch.cluster.metadata.IndexMetaData;
import org.elasticsearch.common.geo.ShapeRelation;
import org.elasticsearch.common.joda.DateMathParser;
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;
Expand All @@ -61,21 +64,21 @@ public void setupProperties() {
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 {
Expand All @@ -84,20 +87,50 @@ public void testRangeQuery() throws Exception {
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);
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);

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

public void testRangeQueryUseDateFormatInMapping() throws Exception {
Settings indexSettings = Settings.builder()
.put(IndexMetaData.SETTING_VERSION_CREATED, Version.CURRENT).build();
IndexSettings idxSettings = IndexSettingsModule.newIndexSettings("test", indexSettings);
QueryShardContext context = new QueryShardContext(0, idxSettings, null, null, null, null, null, xContentRegistry(),
writableRegistry(), null, null, () -> nowInMillis, null);

RangeFieldType fieldType = new RangeFieldType(RangeType.DATE, Version.CURRENT);
fieldType.setName(FIELDNAME);
fieldType.setIndexOptions(IndexOptions.DOCS);
ShapeRelation relation = randomFrom(ShapeRelation.values());
DateTime from = DateTime.now();
DateTime to = DateTime.now().plusDays(DISTANCE);

// Test default date format
DateMathParser defaultParser = new DateMathParser(DateFieldMapper.DEFAULT_DATE_TIME_FORMATTER);
assertEquals(
RangeType.DATE.rangeQuery(FIELDNAME, true, from, to, true,
true, relation, null, defaultParser, context),
fieldType.rangeQuery(from, to, true, true, relation, null, null, context));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure what is tested here, can you explain?
As far as I can see, fieldType.rangeQuery only redirects to DATE#rangeQuery, so other than checking if the parser gets picked up, this test is not doing much in my opinion, but I might miss something.
I'd prefer it it would check that the from/to values are parsed correctly using the parser supplied by fieldType.setDateTimeFormatter. For that I think the from/to values should be String representations of dates that DEFAULT_DATE_TIME_FORMATTER would reject otherwise. I'd like to see a test that checks that using the DEFAULT_DATE_TIME_FORMATTER we get an error (expectThrows) and with the right parser the query contains the expected min/max values. Accessing the min/max values of the Lucene query might be a bit tricky on first inspection of the code, but I think most shape relations should produce LongRange queries which Query can be cast to to use the getters.


// Test using date format in mapping
FormatDateTimeFormatter formatter = Joda.forPattern( "strict_date_optional_time||epoch_millis");
fieldType.setDateTimeFormatter(formatter);
assertEquals(
RangeType.DATE.rangeQuery(FIELDNAME, true, from, to, true,
true, relation, null, fieldType.dateMathParser(), context),
fieldType.rangeQuery(from, to, true, true, relation, null, null, context));
}

private Query getExpectedRangeQuery(ShapeRelation relation, Object from, Object to, boolean includeLower, boolean includeUpper) {
switch (type) {
case DATE:
Expand Down Expand Up @@ -277,14 +310,14 @@ 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);
RangeFieldType ft = new RangeFieldType(type, Version.CURRENT);
ft.setName(FIELDNAME);
ft.setIndexOptions(IndexOptions.DOCS);

Expand Down