Skip to content
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

Fix range query on date fields for number inputs #63692

Merged
merged 17 commits into from
Dec 1, 2020
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,7 @@ public void testSimpleDateRange() throws Exception {
createIndex("test");
client().prepareIndex("test").setId("1").setSource("field", "2010-01-05T02:00").get();
client().prepareIndex("test").setId("2").setSource("field", "2010-01-06T02:00").get();
client().prepareIndex("test").setId("3").setSource("field", "1967-01-01T00:00").get();
ensureGreen();
refresh();
SearchResponse searchResponse = client().prepareSearch("test").setQuery(QueryBuilders.rangeQuery("field").gte("2010-01-03||+2d")
Expand All @@ -223,6 +224,22 @@ public void testSimpleDateRange() throws Exception {
searchResponse = client().prepareSearch("test").setQuery(
QueryBuilders.queryStringQuery("field:[2010-01-03||+2d TO 2010-01-04||+2d/d]")).get();
assertHitCount(searchResponse, 2L);

// a string value of "1000" should be parsed as the year 1000 and return all three docs
searchResponse = client().prepareSearch("test")
.setQuery(QueryBuilders.rangeQuery("field").gt("1000"))
.get();
assertNoFailures(searchResponse);
assertHitCount(searchResponse, 3L);

// a numeric value of 1000 should be parsed as 1000 millis since epoch and return only docs after 1970
searchResponse = client().prepareSearch("test")
.setQuery(QueryBuilders.rangeQuery("field").gt(1000))
.get();
assertNoFailures(searchResponse);
assertHitCount(searchResponse, 2L);
assertEquals("1", searchResponse.getHits().getHits()[0].getId());
assertEquals("2", searchResponse.getHits().getHits()[1].getId());
}

public void testSimpleTerminateAfterCount() throws Exception {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ public final class DateFieldMapper extends ParametrizedFieldMapper {
public static final String CONTENT_TYPE = "date";
public static final String DATE_NANOS_CONTENT_TYPE = "date_nanos";
public static final DateFormatter DEFAULT_DATE_TIME_FORMATTER = DateFormatter.forPattern("strict_date_optional_time||epoch_millis");
private static final DateMathParser EPOCH_MILLIS_PARSER = DateFormatter.forPattern("epoch_millis").toDateMathParser();

public enum Resolution {
MILLISECONDS(CONTENT_TYPE, NumericType.DATE) {
Expand Down Expand Up @@ -349,9 +350,17 @@ public Query rangeQuery(Object lowerTerm, Object upperTerm, boolean includeLower
throw new IllegalArgumentException("Field [" + name() + "] of type [" + typeName() +
"] does not support DISJOINT ranges");
}
DateMathParser parser = forcedDateParser == null
? dateMathParser
: forcedDateParser;
DateMathParser parser;
if (forcedDateParser == null) {
if (lowerTerm instanceof Integer || upperTerm instanceof Integer) {
cbuescher marked this conversation as resolved.
Show resolved Hide resolved
// force epoch_millis
parser = EPOCH_MILLIS_PARSER;
cbuescher marked this conversation as resolved.
Show resolved Hide resolved
} else {
parser = dateMathParser;
}
} else {
parser = forcedDateParser;
}
return dateRangeQuery(lowerTerm, upperTerm, includeLower, includeUpper, timeZone, parser, context, resolution, (l, u) -> {
Query query = LongPoint.newRangeQuery(name(), l, u);
if (hasDocValues()) {
Expand Down Expand Up @@ -443,7 +452,12 @@ public Relation isFieldWithinQuery(IndexReader reader,
Object from, Object to, boolean includeLower, boolean includeUpper,
ZoneId timeZone, DateMathParser dateParser, QueryRewriteContext context) throws IOException {
if (dateParser == null) {
dateParser = this.dateMathParser;
if (from instanceof Integer || to instanceof Integer) {
// force epoch_millis
dateParser = EPOCH_MILLIS_PARSER;
} else {
dateParser = this.dateMathParser;
}
}

long fromInclusive = Long.MIN_VALUE;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
import org.apache.lucene.search.Query;
import org.apache.lucene.search.TermInSetQuery;
import org.elasticsearch.common.ParsingException;
import org.elasticsearch.common.time.DateFormatter;
import org.elasticsearch.common.time.DateMathParser;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.test.AbstractQueryTestCase;

Expand Down Expand Up @@ -97,7 +99,7 @@ public void testFromJson() throws IOException {
protected QueryBuilder parseQuery(XContentParser parser) throws IOException {
QueryBuilder query = super.parseQuery(parser);
assertThat(query, instanceOf(IdsQueryBuilder.class));
return (IdsQueryBuilder) query;
return query;
}

@Override
Expand All @@ -109,4 +111,18 @@ public void testMustRewrite() throws IOException {
() -> queryBuilder.toQuery(context));
assertEquals("Rewrite first", e.getMessage());
}

public void testFoo() {
cbuescher marked this conversation as resolved.
Show resolved Hide resolved
DateMathParser dateMathParser = DateFormatter.forPattern("strict_date_optional_time||epoch_millis").toDateMathParser();
System.out.println(dateMathParser.parse("10", null).toEpochMilli());
System.out.println(dateMathParser.parse("100", null).toEpochMilli());
System.out.println(dateMathParser.parse("999", null).toEpochMilli());
System.out.println(dateMathParser.parse("1000", null).toEpochMilli());
System.out.println(dateMathParser.parse("1500", null).toEpochMilli());
System.out.println(dateMathParser.parse("1968", null).toEpochMilli());
System.out.println(dateMathParser.parse("1969", null).toEpochMilli());
System.out.println(dateMathParser.parse("1970", null).toEpochMilli());
System.out.println(dateMathParser.parse("1990", null).toEpochMilli());
System.out.println(dateMathParser.parse("10000", null).toEpochMilli());
}
}