Date Mapping: Support "date math" when searching, closes #1708.
This commit is contained in:
parent
eb9503f674
commit
f997315f54
|
@ -42,7 +42,7 @@ public class ExistsFieldQueryExtension implements FieldQueryExtension {
|
||||||
MapperService.SmartNameFieldMappers smartNameFieldMappers = parseContext.smartFieldMappers(fieldName);
|
MapperService.SmartNameFieldMappers smartNameFieldMappers = parseContext.smartFieldMappers(fieldName);
|
||||||
if (smartNameFieldMappers != null) {
|
if (smartNameFieldMappers != null) {
|
||||||
if (smartNameFieldMappers.hasMapper()) {
|
if (smartNameFieldMappers.hasMapper()) {
|
||||||
filter = smartNameFieldMappers.mapper().rangeFilter(null, null, true, true);
|
filter = smartNameFieldMappers.mapper().rangeFilter(null, null, true, true, parseContext);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (filter == null) {
|
if (filter == null) {
|
||||||
|
|
|
@ -167,7 +167,7 @@ public class MapperQueryParser extends QueryParser {
|
||||||
if (fieldMappers != null) {
|
if (fieldMappers != null) {
|
||||||
currentMapper = fieldMappers.fieldMappers().mapper();
|
currentMapper = fieldMappers.fieldMappers().mapper();
|
||||||
if (currentMapper != null) {
|
if (currentMapper != null) {
|
||||||
Query rangeQuery = currentMapper.rangeQuery(part1, part2, inclusive, inclusive);
|
Query rangeQuery = currentMapper.rangeQuery(part1, part2, inclusive, inclusive, parseContext);
|
||||||
return wrapSmartNameQuery(rangeQuery, fieldMappers, parseContext);
|
return wrapSmartNameQuery(rangeQuery, fieldMappers, parseContext);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,7 +44,7 @@ public class MissingFieldQueryExtension implements FieldQueryExtension {
|
||||||
MapperService.SmartNameFieldMappers smartNameFieldMappers = parseContext.smartFieldMappers(fieldName);
|
MapperService.SmartNameFieldMappers smartNameFieldMappers = parseContext.smartFieldMappers(fieldName);
|
||||||
if (smartNameFieldMappers != null) {
|
if (smartNameFieldMappers != null) {
|
||||||
if (smartNameFieldMappers.hasMapper()) {
|
if (smartNameFieldMappers.hasMapper()) {
|
||||||
filter = smartNameFieldMappers.mapper().rangeFilter(null, null, true, true);
|
filter = smartNameFieldMappers.mapper().rangeFilter(null, null, true, true, parseContext);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (filter == null) {
|
if (filter == null) {
|
||||||
|
|
|
@ -0,0 +1,227 @@
|
||||||
|
package org.elasticsearch.common.joda;
|
||||||
|
|
||||||
|
import org.elasticsearch.ElasticSearchParseException;
|
||||||
|
import org.joda.time.DateTimeZone;
|
||||||
|
import org.joda.time.MutableDateTime;
|
||||||
|
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
public class DateMathParser {
|
||||||
|
|
||||||
|
private final FormatDateTimeFormatter dateTimeFormatter;
|
||||||
|
|
||||||
|
private final TimeUnit timeUnit;
|
||||||
|
|
||||||
|
public DateMathParser(FormatDateTimeFormatter dateTimeFormatter, TimeUnit timeUnit) {
|
||||||
|
this.dateTimeFormatter = dateTimeFormatter;
|
||||||
|
this.timeUnit = timeUnit;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long parse(String text, long now) {
|
||||||
|
return parse(text, now, false, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public long parseUpperInclusive(String text, long now) {
|
||||||
|
return parse(text, now, true, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public long parse(String text, long now, boolean roundUp, boolean upperInclusive) {
|
||||||
|
long time;
|
||||||
|
String mathString;
|
||||||
|
if (text.startsWith("now")) {
|
||||||
|
time = now;
|
||||||
|
mathString = text.substring("now".length());
|
||||||
|
} else {
|
||||||
|
int index = text.indexOf("||");
|
||||||
|
String parseString;
|
||||||
|
if (index == -1) {
|
||||||
|
parseString = text;
|
||||||
|
mathString = ""; // nothing else
|
||||||
|
} else {
|
||||||
|
parseString = text.substring(0, index);
|
||||||
|
mathString = text.substring(index + 2);
|
||||||
|
}
|
||||||
|
if (upperInclusive) {
|
||||||
|
time = parseUpperInclusiveStringValue(parseString);
|
||||||
|
} else {
|
||||||
|
time = parseStringValue(parseString);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mathString.isEmpty()) {
|
||||||
|
return time;
|
||||||
|
}
|
||||||
|
|
||||||
|
return parseMath(mathString, time, roundUp);
|
||||||
|
}
|
||||||
|
|
||||||
|
private long parseMath(String mathString, long time, boolean roundUp) throws ElasticSearchParseException {
|
||||||
|
MutableDateTime dateTime = new MutableDateTime(time, DateTimeZone.UTC);
|
||||||
|
try {
|
||||||
|
for (int i = 0; i < mathString.length(); ) {
|
||||||
|
char c = mathString.charAt(i++);
|
||||||
|
int type;
|
||||||
|
if (c == '/') {
|
||||||
|
type = 0;
|
||||||
|
} else if (c == '+') {
|
||||||
|
type = 1;
|
||||||
|
} else if (c == '-') {
|
||||||
|
type = 2;
|
||||||
|
} else {
|
||||||
|
throw new ElasticSearchParseException("operator not supported for date math [" + mathString + "]");
|
||||||
|
}
|
||||||
|
|
||||||
|
int num;
|
||||||
|
if (!Character.isDigit(mathString.charAt(i))) {
|
||||||
|
num = 1;
|
||||||
|
} else {
|
||||||
|
int numFrom = i;
|
||||||
|
while (Character.isDigit(mathString.charAt(i))) {
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
num = Integer.parseInt(mathString.substring(numFrom, i));
|
||||||
|
}
|
||||||
|
if (type == 0) {
|
||||||
|
// rounding is only allowed on whole numbers
|
||||||
|
if (num != 1) {
|
||||||
|
throw new ElasticSearchParseException("rounding `/` can only be used on single unit types [" + mathString + "]");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
char unit = mathString.charAt(i++);
|
||||||
|
switch (unit) {
|
||||||
|
case 'M':
|
||||||
|
if (type == 0) {
|
||||||
|
if (roundUp) {
|
||||||
|
dateTime.monthOfYear().roundCeiling();
|
||||||
|
} else {
|
||||||
|
dateTime.monthOfYear().roundFloor();
|
||||||
|
}
|
||||||
|
} else if (type == 1) {
|
||||||
|
dateTime.addMonths(num);
|
||||||
|
} else if (type == 2) {
|
||||||
|
dateTime.addMonths(-num);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'w':
|
||||||
|
if (type == 0) {
|
||||||
|
if (roundUp) {
|
||||||
|
dateTime.weekOfWeekyear().roundCeiling();
|
||||||
|
} else {
|
||||||
|
dateTime.weekOfWeekyear().roundFloor();
|
||||||
|
}
|
||||||
|
} else if (type == 1) {
|
||||||
|
dateTime.addWeeks(num);
|
||||||
|
} else if (type == 2) {
|
||||||
|
dateTime.addWeeks(-num);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'd':
|
||||||
|
if (type == 0) {
|
||||||
|
if (roundUp) {
|
||||||
|
dateTime.dayOfMonth().roundCeiling();
|
||||||
|
} else {
|
||||||
|
dateTime.dayOfMonth().roundFloor();
|
||||||
|
}
|
||||||
|
} else if (type == 1) {
|
||||||
|
dateTime.addDays(num);
|
||||||
|
} else if (type == 2) {
|
||||||
|
dateTime.addDays(-num);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'h':
|
||||||
|
case 'H':
|
||||||
|
if (type == 0) {
|
||||||
|
if (roundUp) {
|
||||||
|
dateTime.hourOfDay().roundCeiling();
|
||||||
|
} else {
|
||||||
|
dateTime.hourOfDay().roundFloor();
|
||||||
|
}
|
||||||
|
} else if (type == 1) {
|
||||||
|
dateTime.addHours(num);
|
||||||
|
} else if (type == 2) {
|
||||||
|
dateTime.addHours(-num);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'm':
|
||||||
|
if (type == 0) {
|
||||||
|
if (roundUp) {
|
||||||
|
dateTime.minuteOfHour().roundCeiling();
|
||||||
|
} else {
|
||||||
|
dateTime.minuteOfHour().roundFloor();
|
||||||
|
}
|
||||||
|
} else if (type == 1) {
|
||||||
|
dateTime.addMinutes(num);
|
||||||
|
} else if (type == 2) {
|
||||||
|
dateTime.addMinutes(-num);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 's':
|
||||||
|
if (type == 0) {
|
||||||
|
if (roundUp) {
|
||||||
|
dateTime.secondOfMinute().roundCeiling();
|
||||||
|
} else {
|
||||||
|
dateTime.secondOfMinute().roundFloor();
|
||||||
|
}
|
||||||
|
} else if (type == 1) {
|
||||||
|
dateTime.addSeconds(num);
|
||||||
|
} else if (type == 2) {
|
||||||
|
dateTime.addSeconds(-num);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new ElasticSearchParseException("unit [" + unit + "] not supported for date math [" + mathString + "]");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
if (e instanceof ElasticSearchParseException) {
|
||||||
|
throw (ElasticSearchParseException) e;
|
||||||
|
}
|
||||||
|
throw new ElasticSearchParseException("failed to parse date math [" + mathString + "]");
|
||||||
|
}
|
||||||
|
return dateTime.getMillis();
|
||||||
|
}
|
||||||
|
|
||||||
|
private long parseStringValue(String value) {
|
||||||
|
try {
|
||||||
|
return dateTimeFormatter.parser().parseMillis(value);
|
||||||
|
} catch (RuntimeException e) {
|
||||||
|
try {
|
||||||
|
long time = Long.parseLong(value);
|
||||||
|
return timeUnit.toMillis(time);
|
||||||
|
} catch (NumberFormatException e1) {
|
||||||
|
throw new ElasticSearchParseException("failed to parse date field [" + value + "], tried both date format [" + dateTimeFormatter.format() + "], and timestamp number", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private long parseUpperInclusiveStringValue(String value) {
|
||||||
|
try {
|
||||||
|
MutableDateTime dateTime = new MutableDateTime(3000, 12, 31, 23, 59, 59, 999, DateTimeZone.UTC);
|
||||||
|
int location = dateTimeFormatter.parser().parseInto(dateTime, value, 0);
|
||||||
|
// if we parsed all the string value, we are good
|
||||||
|
if (location == value.length()) {
|
||||||
|
return dateTime.getMillis();
|
||||||
|
}
|
||||||
|
// if we did not manage to parse, or the year is really high year which is unreasonable
|
||||||
|
// see if its a number
|
||||||
|
if (location <= 0 || dateTime.getYear() > 5000) {
|
||||||
|
try {
|
||||||
|
long time = Long.parseLong(value);
|
||||||
|
return timeUnit.toMillis(time);
|
||||||
|
} catch (NumberFormatException e1) {
|
||||||
|
throw new ElasticSearchParseException("failed to parse date field [" + value + "], tried both date format [" + dateTimeFormatter.format() + "], and timestamp number");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return dateTime.getMillis();
|
||||||
|
} catch (RuntimeException e) {
|
||||||
|
try {
|
||||||
|
long time = Long.parseLong(value);
|
||||||
|
return timeUnit.toMillis(time);
|
||||||
|
} catch (NumberFormatException e1) {
|
||||||
|
throw new ElasticSearchParseException("failed to parse date field [" + value + "], tried both date format [" + dateTimeFormatter.format() + "], and timestamp number", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -198,12 +198,12 @@ public interface FieldMapper<T> {
|
||||||
/**
|
/**
|
||||||
* Constructs a range query based on the mapper.
|
* Constructs a range query based on the mapper.
|
||||||
*/
|
*/
|
||||||
Query rangeQuery(String lowerTerm, String upperTerm, boolean includeLower, boolean includeUpper);
|
Query rangeQuery(String lowerTerm, String upperTerm, boolean includeLower, boolean includeUpper, @Nullable QueryParseContext context);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a range query filter based on the mapper.
|
* Constructs a range query filter based on the mapper.
|
||||||
*/
|
*/
|
||||||
Filter rangeFilter(String lowerTerm, String upperTerm, boolean includeLower, boolean includeUpper);
|
Filter rangeFilter(String lowerTerm, String upperTerm, boolean includeLower, boolean includeUpper, @Nullable QueryParseContext context);
|
||||||
|
|
||||||
FieldDataType fieldDataType();
|
FieldDataType fieldDataType();
|
||||||
}
|
}
|
||||||
|
|
|
@ -395,7 +395,7 @@ public abstract class AbstractFieldMapper<T> implements FieldMapper<T>, Mapper {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Query rangeQuery(String lowerTerm, String upperTerm, boolean includeLower, boolean includeUpper) {
|
public Query rangeQuery(String lowerTerm, String upperTerm, boolean includeLower, boolean includeUpper, @Nullable QueryParseContext context) {
|
||||||
return new TermRangeQuery(names.indexName(),
|
return new TermRangeQuery(names.indexName(),
|
||||||
lowerTerm == null ? null : indexedValue(lowerTerm),
|
lowerTerm == null ? null : indexedValue(lowerTerm),
|
||||||
upperTerm == null ? null : indexedValue(upperTerm),
|
upperTerm == null ? null : indexedValue(upperTerm),
|
||||||
|
@ -403,7 +403,7 @@ public abstract class AbstractFieldMapper<T> implements FieldMapper<T>, Mapper {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Filter rangeFilter(String lowerTerm, String upperTerm, boolean includeLower, boolean includeUpper) {
|
public Filter rangeFilter(String lowerTerm, String upperTerm, boolean includeLower, boolean includeUpper, @Nullable QueryParseContext context) {
|
||||||
return new TermRangeFilter(names.indexName(),
|
return new TermRangeFilter(names.indexName(),
|
||||||
lowerTerm == null ? null : indexedValue(lowerTerm),
|
lowerTerm == null ? null : indexedValue(lowerTerm),
|
||||||
upperTerm == null ? null : indexedValue(upperTerm),
|
upperTerm == null ? null : indexedValue(upperTerm),
|
||||||
|
|
|
@ -167,7 +167,7 @@ public class ByteFieldMapper extends NumberFieldMapper<Byte> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Query rangeQuery(String lowerTerm, String upperTerm, boolean includeLower, boolean includeUpper) {
|
public Query rangeQuery(String lowerTerm, String upperTerm, boolean includeLower, boolean includeUpper, @Nullable QueryParseContext context) {
|
||||||
return NumericRangeQuery.newIntRange(names.indexName(), precisionStep,
|
return NumericRangeQuery.newIntRange(names.indexName(), precisionStep,
|
||||||
lowerTerm == null ? null : Integer.parseInt(lowerTerm),
|
lowerTerm == null ? null : Integer.parseInt(lowerTerm),
|
||||||
upperTerm == null ? null : Integer.parseInt(upperTerm),
|
upperTerm == null ? null : Integer.parseInt(upperTerm),
|
||||||
|
@ -182,7 +182,7 @@ public class ByteFieldMapper extends NumberFieldMapper<Byte> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Filter rangeFilter(String lowerTerm, String upperTerm, boolean includeLower, boolean includeUpper) {
|
public Filter rangeFilter(String lowerTerm, String upperTerm, boolean includeLower, boolean includeUpper, @Nullable QueryParseContext context) {
|
||||||
return NumericRangeFilter.newIntRange(names.indexName(), precisionStep,
|
return NumericRangeFilter.newIntRange(names.indexName(), precisionStep,
|
||||||
lowerTerm == null ? null : Integer.parseInt(lowerTerm),
|
lowerTerm == null ? null : Integer.parseInt(lowerTerm),
|
||||||
upperTerm == null ? null : Integer.parseInt(upperTerm),
|
upperTerm == null ? null : Integer.parseInt(upperTerm),
|
||||||
|
@ -190,7 +190,7 @@ public class ByteFieldMapper extends NumberFieldMapper<Byte> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Filter rangeFilter(FieldDataCache fieldDataCache, String lowerTerm, String upperTerm, boolean includeLower, boolean includeUpper) {
|
public Filter rangeFilter(FieldDataCache fieldDataCache, String lowerTerm, String upperTerm, boolean includeLower, boolean includeUpper, @Nullable QueryParseContext context) {
|
||||||
return NumericRangeFieldDataFilter.newByteRange(fieldDataCache, names.indexName(),
|
return NumericRangeFieldDataFilter.newByteRange(fieldDataCache, names.indexName(),
|
||||||
lowerTerm == null ? null : Byte.parseByte(lowerTerm),
|
lowerTerm == null ? null : Byte.parseByte(lowerTerm),
|
||||||
upperTerm == null ? null : Byte.parseByte(upperTerm),
|
upperTerm == null ? null : Byte.parseByte(upperTerm),
|
||||||
|
|
|
@ -29,6 +29,7 @@ import org.apache.lucene.util.NumericUtils;
|
||||||
import org.elasticsearch.common.Nullable;
|
import org.elasticsearch.common.Nullable;
|
||||||
import org.elasticsearch.common.Numbers;
|
import org.elasticsearch.common.Numbers;
|
||||||
import org.elasticsearch.common.Strings;
|
import org.elasticsearch.common.Strings;
|
||||||
|
import org.elasticsearch.common.joda.DateMathParser;
|
||||||
import org.elasticsearch.common.joda.FormatDateTimeFormatter;
|
import org.elasticsearch.common.joda.FormatDateTimeFormatter;
|
||||||
import org.elasticsearch.common.joda.Joda;
|
import org.elasticsearch.common.joda.Joda;
|
||||||
import org.elasticsearch.common.unit.TimeValue;
|
import org.elasticsearch.common.unit.TimeValue;
|
||||||
|
@ -41,8 +42,6 @@ import org.elasticsearch.index.field.data.FieldDataType;
|
||||||
import org.elasticsearch.index.mapper.*;
|
import org.elasticsearch.index.mapper.*;
|
||||||
import org.elasticsearch.index.query.QueryParseContext;
|
import org.elasticsearch.index.query.QueryParseContext;
|
||||||
import org.elasticsearch.index.search.NumericRangeFieldDataFilter;
|
import org.elasticsearch.index.search.NumericRangeFieldDataFilter;
|
||||||
import org.joda.time.DateTimeZone;
|
|
||||||
import org.joda.time.MutableDateTime;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
@ -133,6 +132,8 @@ public class DateFieldMapper extends NumberFieldMapper<Long> {
|
||||||
|
|
||||||
private final boolean parseUpperInclusive;
|
private final boolean parseUpperInclusive;
|
||||||
|
|
||||||
|
private final DateMathParser dateMathParser;
|
||||||
|
|
||||||
private String nullValue;
|
private String nullValue;
|
||||||
|
|
||||||
protected final TimeUnit timeUnit;
|
protected final TimeUnit timeUnit;
|
||||||
|
@ -148,6 +149,7 @@ public class DateFieldMapper extends NumberFieldMapper<Long> {
|
||||||
this.nullValue = nullValue;
|
this.nullValue = nullValue;
|
||||||
this.timeUnit = timeUnit;
|
this.timeUnit = timeUnit;
|
||||||
this.parseUpperInclusive = parseUpperInclusive;
|
this.parseUpperInclusive = parseUpperInclusive;
|
||||||
|
this.dateMathParser = new DateMathParser(dateTimeFormatter, timeUnit);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -205,7 +207,7 @@ public class DateFieldMapper extends NumberFieldMapper<Long> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Query fuzzyQuery(String value, String minSim, int prefixLength, int maxExpansions) {
|
public Query fuzzyQuery(String value, String minSim, int prefixLength, int maxExpansions) {
|
||||||
long iValue = parseStringValue(value);
|
long iValue = dateMathParser.parse(value, System.currentTimeMillis());
|
||||||
long iSim;
|
long iSim;
|
||||||
try {
|
try {
|
||||||
iSim = TimeValue.parseTimeValue(minSim, null).millis();
|
iSim = TimeValue.parseTimeValue(minSim, null).millis();
|
||||||
|
@ -221,7 +223,7 @@ public class DateFieldMapper extends NumberFieldMapper<Long> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Query fuzzyQuery(String value, double minSim, int prefixLength, int maxExpansions) {
|
public Query fuzzyQuery(String value, double minSim, int prefixLength, int maxExpansions) {
|
||||||
long iValue = parseStringValue(value);
|
long iValue = dateMathParser.parse(value, System.currentTimeMillis());
|
||||||
long iSim = (long) (minSim * dFuzzyFactor);
|
long iSim = (long) (minSim * dFuzzyFactor);
|
||||||
return NumericRangeQuery.newLongRange(names.indexName(), precisionStep,
|
return NumericRangeQuery.newLongRange(names.indexName(), precisionStep,
|
||||||
iValue - iSim,
|
iValue - iSim,
|
||||||
|
@ -231,39 +233,44 @@ public class DateFieldMapper extends NumberFieldMapper<Long> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Query fieldQuery(String value, @Nullable QueryParseContext context) {
|
public Query fieldQuery(String value, @Nullable QueryParseContext context) {
|
||||||
long lValue = parseStringValue(value);
|
long now = context == null ? System.currentTimeMillis() : context.nowInMillis();
|
||||||
|
long lValue = dateMathParser.parse(value, now);
|
||||||
return NumericRangeQuery.newLongRange(names.indexName(), precisionStep,
|
return NumericRangeQuery.newLongRange(names.indexName(), precisionStep,
|
||||||
lValue, lValue, true, true);
|
lValue, lValue, true, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Query rangeQuery(String lowerTerm, String upperTerm, boolean includeLower, boolean includeUpper) {
|
public Query rangeQuery(String lowerTerm, String upperTerm, boolean includeLower, boolean includeUpper, @Nullable QueryParseContext context) {
|
||||||
|
long now = context == null ? System.currentTimeMillis() : context.nowInMillis();
|
||||||
return NumericRangeQuery.newLongRange(names.indexName(), precisionStep,
|
return NumericRangeQuery.newLongRange(names.indexName(), precisionStep,
|
||||||
lowerTerm == null ? null : parseStringValue(lowerTerm),
|
lowerTerm == null ? null : dateMathParser.parse(lowerTerm, now),
|
||||||
upperTerm == null ? null : includeUpper ? parseUpperInclusiveStringValue(upperTerm) : parseStringValue(upperTerm),
|
upperTerm == null ? null : (includeUpper && parseUpperInclusive) ? dateMathParser.parseUpperInclusive(upperTerm, now) : dateMathParser.parse(upperTerm, now),
|
||||||
includeLower, includeUpper);
|
includeLower, includeUpper);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Filter fieldFilter(String value, @Nullable QueryParseContext context) {
|
public Filter fieldFilter(String value, @Nullable QueryParseContext context) {
|
||||||
long lValue = parseStringValue(value);
|
long now = context == null ? System.currentTimeMillis() : context.nowInMillis();
|
||||||
|
long lValue = dateMathParser.parse(value, now);
|
||||||
return NumericRangeFilter.newLongRange(names.indexName(), precisionStep,
|
return NumericRangeFilter.newLongRange(names.indexName(), precisionStep,
|
||||||
lValue, lValue, true, true);
|
lValue, lValue, true, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Filter rangeFilter(String lowerTerm, String upperTerm, boolean includeLower, boolean includeUpper) {
|
public Filter rangeFilter(String lowerTerm, String upperTerm, boolean includeLower, boolean includeUpper, @Nullable QueryParseContext context) {
|
||||||
|
long now = context == null ? System.currentTimeMillis() : context.nowInMillis();
|
||||||
return NumericRangeFilter.newLongRange(names.indexName(), precisionStep,
|
return NumericRangeFilter.newLongRange(names.indexName(), precisionStep,
|
||||||
lowerTerm == null ? null : parseStringValue(lowerTerm),
|
lowerTerm == null ? null : dateMathParser.parse(lowerTerm, now),
|
||||||
upperTerm == null ? null : includeUpper ? parseUpperInclusiveStringValue(upperTerm) : parseStringValue(upperTerm),
|
upperTerm == null ? null : (includeUpper && parseUpperInclusive) ? dateMathParser.parseUpperInclusive(upperTerm, now) : dateMathParser.parse(upperTerm, now),
|
||||||
includeLower, includeUpper);
|
includeLower, includeUpper);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Filter rangeFilter(FieldDataCache fieldDataCache, String lowerTerm, String upperTerm, boolean includeLower, boolean includeUpper) {
|
public Filter rangeFilter(FieldDataCache fieldDataCache, String lowerTerm, String upperTerm, boolean includeLower, boolean includeUpper, @Nullable QueryParseContext context) {
|
||||||
|
long now = context == null ? System.currentTimeMillis() : context.nowInMillis();
|
||||||
return NumericRangeFieldDataFilter.newLongRange(fieldDataCache, names.indexName(),
|
return NumericRangeFieldDataFilter.newLongRange(fieldDataCache, names.indexName(),
|
||||||
lowerTerm == null ? null : parseStringValue(lowerTerm),
|
lowerTerm == null ? null : dateMathParser.parse(lowerTerm, now),
|
||||||
upperTerm == null ? null : includeUpper ? parseUpperInclusiveStringValue(upperTerm) : parseStringValue(upperTerm),
|
upperTerm == null ? null : (includeUpper && parseUpperInclusive) ? dateMathParser.parseUpperInclusive(upperTerm, now) : dateMathParser.parse(upperTerm, now),
|
||||||
includeLower, includeUpper);
|
includeLower, includeUpper);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -394,7 +401,7 @@ public class DateFieldMapper extends NumberFieldMapper<Long> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected long parseStringValue(String value) {
|
private long parseStringValue(String value) {
|
||||||
try {
|
try {
|
||||||
return dateTimeFormatter.parser().parseMillis(value);
|
return dateTimeFormatter.parser().parseMillis(value);
|
||||||
} catch (RuntimeException e) {
|
} catch (RuntimeException e) {
|
||||||
|
@ -406,36 +413,4 @@ public class DateFieldMapper extends NumberFieldMapper<Long> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected long parseUpperInclusiveStringValue(String value) {
|
|
||||||
if (!parseUpperInclusive) {
|
|
||||||
return parseStringValue(value);
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
MutableDateTime dateTime = new MutableDateTime(3000, 12, 31, 23, 59, 59, 999, DateTimeZone.UTC);
|
|
||||||
int location = dateTimeFormatter.parser().parseInto(dateTime, value, 0);
|
|
||||||
// if we parsed all the string value, we are good
|
|
||||||
if (location == value.length()) {
|
|
||||||
return dateTime.getMillis();
|
|
||||||
}
|
|
||||||
// if we did not manage to parse, or the year is really high year which is unreasonable
|
|
||||||
// see if its a number
|
|
||||||
if (location <= 0 || dateTime.getYear() > 5000) {
|
|
||||||
try {
|
|
||||||
long time = Long.parseLong(value);
|
|
||||||
return timeUnit.toMillis(time);
|
|
||||||
} catch (NumberFormatException e1) {
|
|
||||||
throw new MapperParsingException("failed to parse date field [" + value + "], tried both date format [" + dateTimeFormatter.format() + "], and timestamp number");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return dateTime.getMillis();
|
|
||||||
} catch (RuntimeException e) {
|
|
||||||
try {
|
|
||||||
long time = Long.parseLong(value);
|
|
||||||
return timeUnit.toMillis(time);
|
|
||||||
} catch (NumberFormatException e1) {
|
|
||||||
throw new MapperParsingException("failed to parse date field [" + value + "], tried both date format [" + dateTimeFormatter.format() + "], and timestamp number", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -164,7 +164,7 @@ public class DoubleFieldMapper extends NumberFieldMapper<Double> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Query rangeQuery(String lowerTerm, String upperTerm, boolean includeLower, boolean includeUpper) {
|
public Query rangeQuery(String lowerTerm, String upperTerm, boolean includeLower, boolean includeUpper, @Nullable QueryParseContext context) {
|
||||||
return NumericRangeQuery.newDoubleRange(names.indexName(), precisionStep,
|
return NumericRangeQuery.newDoubleRange(names.indexName(), precisionStep,
|
||||||
lowerTerm == null ? null : Double.parseDouble(lowerTerm),
|
lowerTerm == null ? null : Double.parseDouble(lowerTerm),
|
||||||
upperTerm == null ? null : Double.parseDouble(upperTerm),
|
upperTerm == null ? null : Double.parseDouble(upperTerm),
|
||||||
|
@ -179,7 +179,7 @@ public class DoubleFieldMapper extends NumberFieldMapper<Double> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Filter rangeFilter(String lowerTerm, String upperTerm, boolean includeLower, boolean includeUpper) {
|
public Filter rangeFilter(String lowerTerm, String upperTerm, boolean includeLower, boolean includeUpper, @Nullable QueryParseContext context) {
|
||||||
return NumericRangeFilter.newDoubleRange(names.indexName(), precisionStep,
|
return NumericRangeFilter.newDoubleRange(names.indexName(), precisionStep,
|
||||||
lowerTerm == null ? null : Double.parseDouble(lowerTerm),
|
lowerTerm == null ? null : Double.parseDouble(lowerTerm),
|
||||||
upperTerm == null ? null : Double.parseDouble(upperTerm),
|
upperTerm == null ? null : Double.parseDouble(upperTerm),
|
||||||
|
@ -191,7 +191,7 @@ public class DoubleFieldMapper extends NumberFieldMapper<Double> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Filter rangeFilter(FieldDataCache fieldDataCache, String lowerTerm, String upperTerm, boolean includeLower, boolean includeUpper) {
|
public Filter rangeFilter(FieldDataCache fieldDataCache, String lowerTerm, String upperTerm, boolean includeLower, boolean includeUpper, @Nullable QueryParseContext context) {
|
||||||
return NumericRangeFieldDataFilter.newDoubleRange(fieldDataCache, names.indexName(),
|
return NumericRangeFieldDataFilter.newDoubleRange(fieldDataCache, names.indexName(),
|
||||||
lowerTerm == null ? null : Double.parseDouble(lowerTerm),
|
lowerTerm == null ? null : Double.parseDouble(lowerTerm),
|
||||||
upperTerm == null ? null : Double.parseDouble(upperTerm),
|
upperTerm == null ? null : Double.parseDouble(upperTerm),
|
||||||
|
|
|
@ -163,7 +163,7 @@ public class FloatFieldMapper extends NumberFieldMapper<Float> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Query rangeQuery(String lowerTerm, String upperTerm, boolean includeLower, boolean includeUpper) {
|
public Query rangeQuery(String lowerTerm, String upperTerm, boolean includeLower, boolean includeUpper, @Nullable QueryParseContext context) {
|
||||||
return NumericRangeQuery.newFloatRange(names.indexName(), precisionStep,
|
return NumericRangeQuery.newFloatRange(names.indexName(), precisionStep,
|
||||||
lowerTerm == null ? null : Float.parseFloat(lowerTerm),
|
lowerTerm == null ? null : Float.parseFloat(lowerTerm),
|
||||||
upperTerm == null ? null : Float.parseFloat(upperTerm),
|
upperTerm == null ? null : Float.parseFloat(upperTerm),
|
||||||
|
@ -178,7 +178,7 @@ public class FloatFieldMapper extends NumberFieldMapper<Float> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Filter rangeFilter(String lowerTerm, String upperTerm, boolean includeLower, boolean includeUpper) {
|
public Filter rangeFilter(String lowerTerm, String upperTerm, boolean includeLower, boolean includeUpper, @Nullable QueryParseContext context) {
|
||||||
return NumericRangeFilter.newFloatRange(names.indexName(), precisionStep,
|
return NumericRangeFilter.newFloatRange(names.indexName(), precisionStep,
|
||||||
lowerTerm == null ? null : Float.parseFloat(lowerTerm),
|
lowerTerm == null ? null : Float.parseFloat(lowerTerm),
|
||||||
upperTerm == null ? null : Float.parseFloat(upperTerm),
|
upperTerm == null ? null : Float.parseFloat(upperTerm),
|
||||||
|
@ -186,7 +186,7 @@ public class FloatFieldMapper extends NumberFieldMapper<Float> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Filter rangeFilter(FieldDataCache fieldDataCache, String lowerTerm, String upperTerm, boolean includeLower, boolean includeUpper) {
|
public Filter rangeFilter(FieldDataCache fieldDataCache, String lowerTerm, String upperTerm, boolean includeLower, boolean includeUpper, @Nullable QueryParseContext context) {
|
||||||
return NumericRangeFieldDataFilter.newFloatRange(fieldDataCache, names.indexName(),
|
return NumericRangeFieldDataFilter.newFloatRange(fieldDataCache, names.indexName(),
|
||||||
lowerTerm == null ? null : Float.parseFloat(lowerTerm),
|
lowerTerm == null ? null : Float.parseFloat(lowerTerm),
|
||||||
upperTerm == null ? null : Float.parseFloat(upperTerm),
|
upperTerm == null ? null : Float.parseFloat(upperTerm),
|
||||||
|
|
|
@ -168,7 +168,7 @@ public class IntegerFieldMapper extends NumberFieldMapper<Integer> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Query rangeQuery(String lowerTerm, String upperTerm, boolean includeLower, boolean includeUpper) {
|
public Query rangeQuery(String lowerTerm, String upperTerm, boolean includeLower, boolean includeUpper, @Nullable QueryParseContext context) {
|
||||||
return NumericRangeQuery.newIntRange(names.indexName(), precisionStep,
|
return NumericRangeQuery.newIntRange(names.indexName(), precisionStep,
|
||||||
lowerTerm == null ? null : Integer.parseInt(lowerTerm),
|
lowerTerm == null ? null : Integer.parseInt(lowerTerm),
|
||||||
upperTerm == null ? null : Integer.parseInt(upperTerm),
|
upperTerm == null ? null : Integer.parseInt(upperTerm),
|
||||||
|
@ -183,7 +183,7 @@ public class IntegerFieldMapper extends NumberFieldMapper<Integer> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Filter rangeFilter(String lowerTerm, String upperTerm, boolean includeLower, boolean includeUpper) {
|
public Filter rangeFilter(String lowerTerm, String upperTerm, boolean includeLower, boolean includeUpper, @Nullable QueryParseContext context) {
|
||||||
return NumericRangeFilter.newIntRange(names.indexName(), precisionStep,
|
return NumericRangeFilter.newIntRange(names.indexName(), precisionStep,
|
||||||
lowerTerm == null ? null : Integer.parseInt(lowerTerm),
|
lowerTerm == null ? null : Integer.parseInt(lowerTerm),
|
||||||
upperTerm == null ? null : Integer.parseInt(upperTerm),
|
upperTerm == null ? null : Integer.parseInt(upperTerm),
|
||||||
|
@ -191,7 +191,7 @@ public class IntegerFieldMapper extends NumberFieldMapper<Integer> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Filter rangeFilter(FieldDataCache fieldDataCache, String lowerTerm, String upperTerm, boolean includeLower, boolean includeUpper) {
|
public Filter rangeFilter(FieldDataCache fieldDataCache, String lowerTerm, String upperTerm, boolean includeLower, boolean includeUpper, @Nullable QueryParseContext context) {
|
||||||
return NumericRangeFieldDataFilter.newIntRange(fieldDataCache, names.indexName(),
|
return NumericRangeFieldDataFilter.newIntRange(fieldDataCache, names.indexName(),
|
||||||
lowerTerm == null ? null : Integer.parseInt(lowerTerm),
|
lowerTerm == null ? null : Integer.parseInt(lowerTerm),
|
||||||
upperTerm == null ? null : Integer.parseInt(upperTerm),
|
upperTerm == null ? null : Integer.parseInt(upperTerm),
|
||||||
|
|
|
@ -168,7 +168,7 @@ public class LongFieldMapper extends NumberFieldMapper<Long> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Query rangeQuery(String lowerTerm, String upperTerm, boolean includeLower, boolean includeUpper) {
|
public Query rangeQuery(String lowerTerm, String upperTerm, boolean includeLower, boolean includeUpper, @Nullable QueryParseContext context) {
|
||||||
return NumericRangeQuery.newLongRange(names.indexName(), precisionStep,
|
return NumericRangeQuery.newLongRange(names.indexName(), precisionStep,
|
||||||
lowerTerm == null ? null : Long.parseLong(lowerTerm),
|
lowerTerm == null ? null : Long.parseLong(lowerTerm),
|
||||||
upperTerm == null ? null : Long.parseLong(upperTerm),
|
upperTerm == null ? null : Long.parseLong(upperTerm),
|
||||||
|
@ -183,7 +183,7 @@ public class LongFieldMapper extends NumberFieldMapper<Long> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Filter rangeFilter(String lowerTerm, String upperTerm, boolean includeLower, boolean includeUpper) {
|
public Filter rangeFilter(String lowerTerm, String upperTerm, boolean includeLower, boolean includeUpper, @Nullable QueryParseContext context) {
|
||||||
return NumericRangeFilter.newLongRange(names.indexName(), precisionStep,
|
return NumericRangeFilter.newLongRange(names.indexName(), precisionStep,
|
||||||
lowerTerm == null ? null : Long.parseLong(lowerTerm),
|
lowerTerm == null ? null : Long.parseLong(lowerTerm),
|
||||||
upperTerm == null ? null : Long.parseLong(upperTerm),
|
upperTerm == null ? null : Long.parseLong(upperTerm),
|
||||||
|
@ -191,7 +191,7 @@ public class LongFieldMapper extends NumberFieldMapper<Long> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Filter rangeFilter(FieldDataCache fieldDataCache, String lowerTerm, String upperTerm, boolean includeLower, boolean includeUpper) {
|
public Filter rangeFilter(FieldDataCache fieldDataCache, String lowerTerm, String upperTerm, boolean includeLower, boolean includeUpper, @Nullable QueryParseContext context) {
|
||||||
return NumericRangeFieldDataFilter.newLongRange(fieldDataCache, names.indexName(),
|
return NumericRangeFieldDataFilter.newLongRange(fieldDataCache, names.indexName(),
|
||||||
lowerTerm == null ? null : Long.parseLong(lowerTerm),
|
lowerTerm == null ? null : Long.parseLong(lowerTerm),
|
||||||
upperTerm == null ? null : Long.parseLong(upperTerm),
|
upperTerm == null ? null : Long.parseLong(upperTerm),
|
||||||
|
|
|
@ -166,7 +166,7 @@ public abstract class NumberFieldMapper<T extends Number> extends AbstractFieldM
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Query fieldQuery(String value, @Nullable QueryParseContext context) {
|
public Query fieldQuery(String value, @Nullable QueryParseContext context) {
|
||||||
return rangeQuery(value, value, true, true);
|
return rangeQuery(value, value, true, true, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -181,19 +181,19 @@ public abstract class NumberFieldMapper<T extends Number> extends AbstractFieldM
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Filter fieldFilter(String value, @Nullable QueryParseContext context) {
|
public Filter fieldFilter(String value, @Nullable QueryParseContext context) {
|
||||||
return rangeFilter(value, value, true, true);
|
return rangeFilter(value, value, true, true, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public abstract Query rangeQuery(String lowerTerm, String upperTerm, boolean includeLower, boolean includeUpper);
|
public abstract Query rangeQuery(String lowerTerm, String upperTerm, boolean includeLower, boolean includeUpper, @Nullable QueryParseContext context);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public abstract Filter rangeFilter(String lowerTerm, String upperTerm, boolean includeLower, boolean includeUpper);
|
public abstract Filter rangeFilter(String lowerTerm, String upperTerm, boolean includeLower, boolean includeUpper, @Nullable QueryParseContext context);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A range filter based on the field data cache.
|
* A range filter based on the field data cache.
|
||||||
*/
|
*/
|
||||||
public abstract Filter rangeFilter(FieldDataCache fieldDataCache, String lowerTerm, String upperTerm, boolean includeLower, boolean includeUpper);
|
public abstract Filter rangeFilter(FieldDataCache fieldDataCache, String lowerTerm, String upperTerm, boolean includeLower, boolean includeUpper, @Nullable QueryParseContext context);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Override the default behavior (to return the string, and return the actual Number instance).
|
* Override the default behavior (to return the string, and return the actual Number instance).
|
||||||
|
|
|
@ -168,7 +168,7 @@ public class ShortFieldMapper extends NumberFieldMapper<Short> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Query rangeQuery(String lowerTerm, String upperTerm, boolean includeLower, boolean includeUpper) {
|
public Query rangeQuery(String lowerTerm, String upperTerm, boolean includeLower, boolean includeUpper, @Nullable QueryParseContext context) {
|
||||||
return NumericRangeQuery.newIntRange(names.indexName(), precisionStep,
|
return NumericRangeQuery.newIntRange(names.indexName(), precisionStep,
|
||||||
lowerTerm == null ? null : Integer.parseInt(lowerTerm),
|
lowerTerm == null ? null : Integer.parseInt(lowerTerm),
|
||||||
upperTerm == null ? null : Integer.parseInt(upperTerm),
|
upperTerm == null ? null : Integer.parseInt(upperTerm),
|
||||||
|
@ -183,7 +183,7 @@ public class ShortFieldMapper extends NumberFieldMapper<Short> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Filter rangeFilter(String lowerTerm, String upperTerm, boolean includeLower, boolean includeUpper) {
|
public Filter rangeFilter(String lowerTerm, String upperTerm, boolean includeLower, boolean includeUpper, @Nullable QueryParseContext context) {
|
||||||
return NumericRangeFilter.newIntRange(names.indexName(), precisionStep,
|
return NumericRangeFilter.newIntRange(names.indexName(), precisionStep,
|
||||||
lowerTerm == null ? null : Integer.parseInt(lowerTerm),
|
lowerTerm == null ? null : Integer.parseInt(lowerTerm),
|
||||||
upperTerm == null ? null : Integer.parseInt(upperTerm),
|
upperTerm == null ? null : Integer.parseInt(upperTerm),
|
||||||
|
@ -191,7 +191,7 @@ public class ShortFieldMapper extends NumberFieldMapper<Short> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Filter rangeFilter(FieldDataCache fieldDataCache, String lowerTerm, String upperTerm, boolean includeLower, boolean includeUpper) {
|
public Filter rangeFilter(FieldDataCache fieldDataCache, String lowerTerm, String upperTerm, boolean includeLower, boolean includeUpper, @Nullable QueryParseContext context) {
|
||||||
return NumericRangeFieldDataFilter.newShortRange(fieldDataCache, names.indexName(),
|
return NumericRangeFieldDataFilter.newShortRange(fieldDataCache, names.indexName(),
|
||||||
lowerTerm == null ? null : Short.parseShort(lowerTerm),
|
lowerTerm == null ? null : Short.parseShort(lowerTerm),
|
||||||
upperTerm == null ? null : Short.parseShort(upperTerm),
|
upperTerm == null ? null : Short.parseShort(upperTerm),
|
||||||
|
|
|
@ -26,6 +26,7 @@ import org.apache.lucene.search.NumericRangeFilter;
|
||||||
import org.apache.lucene.search.NumericRangeQuery;
|
import org.apache.lucene.search.NumericRangeQuery;
|
||||||
import org.apache.lucene.search.Query;
|
import org.apache.lucene.search.Query;
|
||||||
import org.apache.lucene.util.NumericUtils;
|
import org.apache.lucene.util.NumericUtils;
|
||||||
|
import org.elasticsearch.common.Nullable;
|
||||||
import org.elasticsearch.common.Numbers;
|
import org.elasticsearch.common.Numbers;
|
||||||
import org.elasticsearch.common.Strings;
|
import org.elasticsearch.common.Strings;
|
||||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||||
|
@ -37,6 +38,7 @@ import org.elasticsearch.index.field.data.FieldDataType;
|
||||||
import org.elasticsearch.index.mapper.*;
|
import org.elasticsearch.index.mapper.*;
|
||||||
import org.elasticsearch.index.mapper.core.FloatFieldMapper;
|
import org.elasticsearch.index.mapper.core.FloatFieldMapper;
|
||||||
import org.elasticsearch.index.mapper.core.NumberFieldMapper;
|
import org.elasticsearch.index.mapper.core.NumberFieldMapper;
|
||||||
|
import org.elasticsearch.index.query.QueryParseContext;
|
||||||
import org.elasticsearch.index.search.NumericRangeFieldDataFilter;
|
import org.elasticsearch.index.search.NumericRangeFieldDataFilter;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
@ -165,7 +167,7 @@ public class BoostFieldMapper extends NumberFieldMapper<Float> implements Intern
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Query rangeQuery(String lowerTerm, String upperTerm, boolean includeLower, boolean includeUpper) {
|
public Query rangeQuery(String lowerTerm, String upperTerm, boolean includeLower, boolean includeUpper, @Nullable QueryParseContext context) {
|
||||||
return NumericRangeQuery.newFloatRange(names.indexName(), precisionStep,
|
return NumericRangeQuery.newFloatRange(names.indexName(), precisionStep,
|
||||||
lowerTerm == null ? null : Float.parseFloat(lowerTerm),
|
lowerTerm == null ? null : Float.parseFloat(lowerTerm),
|
||||||
upperTerm == null ? null : Float.parseFloat(upperTerm),
|
upperTerm == null ? null : Float.parseFloat(upperTerm),
|
||||||
|
@ -173,7 +175,7 @@ public class BoostFieldMapper extends NumberFieldMapper<Float> implements Intern
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Filter rangeFilter(String lowerTerm, String upperTerm, boolean includeLower, boolean includeUpper) {
|
public Filter rangeFilter(String lowerTerm, String upperTerm, boolean includeLower, boolean includeUpper, @Nullable QueryParseContext context) {
|
||||||
return NumericRangeFilter.newFloatRange(names.indexName(), precisionStep,
|
return NumericRangeFilter.newFloatRange(names.indexName(), precisionStep,
|
||||||
lowerTerm == null ? null : Float.parseFloat(lowerTerm),
|
lowerTerm == null ? null : Float.parseFloat(lowerTerm),
|
||||||
upperTerm == null ? null : Float.parseFloat(upperTerm),
|
upperTerm == null ? null : Float.parseFloat(upperTerm),
|
||||||
|
@ -181,7 +183,7 @@ public class BoostFieldMapper extends NumberFieldMapper<Float> implements Intern
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Filter rangeFilter(FieldDataCache fieldDataCache, String lowerTerm, String upperTerm, boolean includeLower, boolean includeUpper) {
|
public Filter rangeFilter(FieldDataCache fieldDataCache, String lowerTerm, String upperTerm, boolean includeLower, boolean includeUpper, @Nullable QueryParseContext context) {
|
||||||
return NumericRangeFieldDataFilter.newFloatRange(fieldDataCache, names.indexName(),
|
return NumericRangeFieldDataFilter.newFloatRange(fieldDataCache, names.indexName(),
|
||||||
lowerTerm == null ? null : Float.parseFloat(lowerTerm),
|
lowerTerm == null ? null : Float.parseFloat(lowerTerm),
|
||||||
upperTerm == null ? null : Float.parseFloat(upperTerm),
|
upperTerm == null ? null : Float.parseFloat(upperTerm),
|
||||||
|
|
|
@ -25,6 +25,7 @@ import org.apache.lucene.document.Fieldable;
|
||||||
import org.apache.lucene.search.*;
|
import org.apache.lucene.search.*;
|
||||||
import org.apache.lucene.util.NumericUtils;
|
import org.apache.lucene.util.NumericUtils;
|
||||||
import org.elasticsearch.ElasticSearchIllegalArgumentException;
|
import org.elasticsearch.ElasticSearchIllegalArgumentException;
|
||||||
|
import org.elasticsearch.common.Nullable;
|
||||||
import org.elasticsearch.common.Numbers;
|
import org.elasticsearch.common.Numbers;
|
||||||
import org.elasticsearch.common.Strings;
|
import org.elasticsearch.common.Strings;
|
||||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||||
|
@ -37,6 +38,7 @@ import org.elasticsearch.index.field.data.FieldDataType;
|
||||||
import org.elasticsearch.index.mapper.*;
|
import org.elasticsearch.index.mapper.*;
|
||||||
import org.elasticsearch.index.mapper.core.LongFieldMapper;
|
import org.elasticsearch.index.mapper.core.LongFieldMapper;
|
||||||
import org.elasticsearch.index.mapper.core.NumberFieldMapper;
|
import org.elasticsearch.index.mapper.core.NumberFieldMapper;
|
||||||
|
import org.elasticsearch.index.query.QueryParseContext;
|
||||||
import org.elasticsearch.index.search.NumericRangeFieldDataFilter;
|
import org.elasticsearch.index.search.NumericRangeFieldDataFilter;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
@ -201,7 +203,7 @@ public class IpFieldMapper extends NumberFieldMapper<Long> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Query rangeQuery(String lowerTerm, String upperTerm, boolean includeLower, boolean includeUpper) {
|
public Query rangeQuery(String lowerTerm, String upperTerm, boolean includeLower, boolean includeUpper, @Nullable QueryParseContext context) {
|
||||||
return NumericRangeQuery.newLongRange(names.indexName(), precisionStep,
|
return NumericRangeQuery.newLongRange(names.indexName(), precisionStep,
|
||||||
lowerTerm == null ? null : ipToLong(lowerTerm),
|
lowerTerm == null ? null : ipToLong(lowerTerm),
|
||||||
upperTerm == null ? null : ipToLong(upperTerm),
|
upperTerm == null ? null : ipToLong(upperTerm),
|
||||||
|
@ -209,7 +211,7 @@ public class IpFieldMapper extends NumberFieldMapper<Long> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Filter rangeFilter(String lowerTerm, String upperTerm, boolean includeLower, boolean includeUpper) {
|
public Filter rangeFilter(String lowerTerm, String upperTerm, boolean includeLower, boolean includeUpper, @Nullable QueryParseContext context) {
|
||||||
return NumericRangeFilter.newLongRange(names.indexName(), precisionStep,
|
return NumericRangeFilter.newLongRange(names.indexName(), precisionStep,
|
||||||
lowerTerm == null ? null : ipToLong(lowerTerm),
|
lowerTerm == null ? null : ipToLong(lowerTerm),
|
||||||
upperTerm == null ? null : ipToLong(upperTerm),
|
upperTerm == null ? null : ipToLong(upperTerm),
|
||||||
|
@ -217,7 +219,7 @@ public class IpFieldMapper extends NumberFieldMapper<Long> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Filter rangeFilter(FieldDataCache fieldDataCache, String lowerTerm, String upperTerm, boolean includeLower, boolean includeUpper) {
|
public Filter rangeFilter(FieldDataCache fieldDataCache, String lowerTerm, String upperTerm, boolean includeLower, boolean includeUpper, @Nullable QueryParseContext context) {
|
||||||
return NumericRangeFieldDataFilter.newLongRange(fieldDataCache, names.indexName(),
|
return NumericRangeFieldDataFilter.newLongRange(fieldDataCache, names.indexName(),
|
||||||
lowerTerm == null ? null : ipToLong(lowerTerm),
|
lowerTerm == null ? null : ipToLong(lowerTerm),
|
||||||
upperTerm == null ? null : ipToLong(upperTerm),
|
upperTerm == null ? null : ipToLong(upperTerm),
|
||||||
|
|
|
@ -75,7 +75,7 @@ public class ExistsFilterParser implements FilterParser {
|
||||||
Filter filter = null;
|
Filter filter = null;
|
||||||
MapperService.SmartNameFieldMappers smartNameFieldMappers = parseContext.smartFieldMappers(fieldName);
|
MapperService.SmartNameFieldMappers smartNameFieldMappers = parseContext.smartFieldMappers(fieldName);
|
||||||
if (smartNameFieldMappers != null && smartNameFieldMappers.hasMapper()) {
|
if (smartNameFieldMappers != null && smartNameFieldMappers.hasMapper()) {
|
||||||
filter = smartNameFieldMappers.mapper().rangeFilter(null, null, true, true);
|
filter = smartNameFieldMappers.mapper().rangeFilter(null, null, true, true, parseContext);
|
||||||
}
|
}
|
||||||
if (filter == null) {
|
if (filter == null) {
|
||||||
filter = new TermRangeFilter(fieldName, null, null, true, true);
|
filter = new TermRangeFilter(fieldName, null, null, true, true);
|
||||||
|
|
|
@ -76,7 +76,7 @@ public class MissingFilterParser implements FilterParser {
|
||||||
Filter filter = null;
|
Filter filter = null;
|
||||||
MapperService.SmartNameFieldMappers smartNameFieldMappers = parseContext.smartFieldMappers(fieldName);
|
MapperService.SmartNameFieldMappers smartNameFieldMappers = parseContext.smartFieldMappers(fieldName);
|
||||||
if (smartNameFieldMappers != null && smartNameFieldMappers.hasMapper()) {
|
if (smartNameFieldMappers != null && smartNameFieldMappers.hasMapper()) {
|
||||||
filter = smartNameFieldMappers.mapper().rangeFilter(null, null, true, true);
|
filter = smartNameFieldMappers.mapper().rangeFilter(null, null, true, true, parseContext);
|
||||||
}
|
}
|
||||||
if (filter == null) {
|
if (filter == null) {
|
||||||
filter = new TermRangeFilter(fieldName, null, null, true, true);
|
filter = new TermRangeFilter(fieldName, null, null, true, true);
|
||||||
|
|
|
@ -119,7 +119,7 @@ public class NumericRangeFilterParser implements FilterParser {
|
||||||
if (!(mapper instanceof NumberFieldMapper)) {
|
if (!(mapper instanceof NumberFieldMapper)) {
|
||||||
throw new QueryParsingException(parseContext.index(), "Field [" + fieldName + "] is not a numeric type");
|
throw new QueryParsingException(parseContext.index(), "Field [" + fieldName + "] is not a numeric type");
|
||||||
}
|
}
|
||||||
Filter filter = ((NumberFieldMapper) mapper).rangeFilter(parseContext.indexCache().fieldData(), from, to, includeLower, includeUpper);
|
Filter filter = ((NumberFieldMapper) mapper).rangeFilter(parseContext.indexCache().fieldData(), from, to, includeLower, includeUpper, parseContext);
|
||||||
|
|
||||||
if (cache) {
|
if (cache) {
|
||||||
filter = parseContext.cacheFilter(filter, cacheKey);
|
filter = parseContext.cacheFilter(filter, cacheKey);
|
||||||
|
|
|
@ -293,4 +293,12 @@ public class QueryParseContext {
|
||||||
}
|
}
|
||||||
return lookup;
|
return lookup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public long nowInMillis() {
|
||||||
|
SearchContext current = SearchContext.current();
|
||||||
|
if (current != null) {
|
||||||
|
return current.nowInMillis();
|
||||||
|
}
|
||||||
|
return System.currentTimeMillis();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -116,7 +116,7 @@ public class RangeFilterParser implements FilterParser {
|
||||||
MapperService.SmartNameFieldMappers smartNameFieldMappers = parseContext.smartFieldMappers(fieldName);
|
MapperService.SmartNameFieldMappers smartNameFieldMappers = parseContext.smartFieldMappers(fieldName);
|
||||||
if (smartNameFieldMappers != null) {
|
if (smartNameFieldMappers != null) {
|
||||||
if (smartNameFieldMappers.hasMapper()) {
|
if (smartNameFieldMappers.hasMapper()) {
|
||||||
filter = smartNameFieldMappers.mapper().rangeFilter(from, to, includeLower, includeUpper);
|
filter = smartNameFieldMappers.mapper().rangeFilter(from, to, includeLower, includeUpper, parseContext);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (filter == null) {
|
if (filter == null) {
|
||||||
|
|
|
@ -108,7 +108,7 @@ public class RangeQueryParser implements QueryParser {
|
||||||
MapperService.SmartNameFieldMappers smartNameFieldMappers = parseContext.smartFieldMappers(fieldName);
|
MapperService.SmartNameFieldMappers smartNameFieldMappers = parseContext.smartFieldMappers(fieldName);
|
||||||
if (smartNameFieldMappers != null) {
|
if (smartNameFieldMappers != null) {
|
||||||
if (smartNameFieldMappers.hasMapper()) {
|
if (smartNameFieldMappers.hasMapper()) {
|
||||||
query = smartNameFieldMappers.mapper().rangeQuery(from, to, includeLower, includeUpper);
|
query = smartNameFieldMappers.mapper().rangeQuery(from, to, includeLower, includeUpper, parseContext);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (query == null) {
|
if (query == null) {
|
||||||
|
|
|
@ -126,4 +126,19 @@ public class SimpleSearchTests extends AbstractNodesTests {
|
||||||
searchResponse = client.prepareSearch("test").setQuery(QueryBuilders.rangeQuery("field").gte("2010-01-05").lt("2010-01-06")).execute().actionGet();
|
searchResponse = client.prepareSearch("test").setQuery(QueryBuilders.rangeQuery("field").gte("2010-01-05").lt("2010-01-06")).execute().actionGet();
|
||||||
assertThat(searchResponse.hits().totalHits(), equalTo(1l));
|
assertThat(searchResponse.hits().totalHits(), equalTo(1l));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void simpleDateMathTests() throws Exception {
|
||||||
|
client.admin().indices().prepareDelete().execute().actionGet();
|
||||||
|
client.admin().indices().prepareCreate("test").setSettings(ImmutableSettings.settingsBuilder()).execute().actionGet();
|
||||||
|
client.prepareIndex("test", "type1", "1").setSource("field", "2010-01-05T02:00").execute().actionGet();
|
||||||
|
client.prepareIndex("test", "type1", "2").setSource("field", "2010-01-06T02:00").execute().actionGet();
|
||||||
|
client.admin().indices().prepareRefresh().execute().actionGet();
|
||||||
|
|
||||||
|
SearchResponse searchResponse = client.prepareSearch("test").setQuery(QueryBuilders.rangeQuery("field").gte("2010-01-03||+2d").lte("2010-01-04||+2d")).execute().actionGet();
|
||||||
|
assertThat(searchResponse.hits().totalHits(), equalTo(2l));
|
||||||
|
|
||||||
|
searchResponse = client.prepareSearch("test").setQuery(QueryBuilders.queryString("field:[2010-01-03||+2d TO 2010-01-04||+2d]")).execute().actionGet();
|
||||||
|
assertThat(searchResponse.hits().totalHits(), equalTo(2l));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,43 @@
|
||||||
|
package org.elasticsearch.test.unit.common.joda;
|
||||||
|
|
||||||
|
import org.elasticsearch.common.joda.DateMathParser;
|
||||||
|
import org.elasticsearch.common.joda.Joda;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
|
import static org.hamcrest.Matchers.equalTo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public class DateMathParserTests {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void dataMathTests() {
|
||||||
|
DateMathParser parser = new DateMathParser(Joda.forPattern("dateOptionalTime"), TimeUnit.MILLISECONDS);
|
||||||
|
|
||||||
|
assertThat(parser.parse("now", 0), equalTo(0l));
|
||||||
|
assertThat(parser.parse("now+m", 0), equalTo(TimeUnit.MINUTES.toMillis(1)));
|
||||||
|
assertThat(parser.parse("now+1m", 0), equalTo(TimeUnit.MINUTES.toMillis(1)));
|
||||||
|
assertThat(parser.parse("now+11m", 0), equalTo(TimeUnit.MINUTES.toMillis(11)));
|
||||||
|
|
||||||
|
assertThat(parser.parse("now+1d", 0), equalTo(TimeUnit.DAYS.toMillis(1)));
|
||||||
|
|
||||||
|
assertThat(parser.parse("now+1m+1s", 0), equalTo(TimeUnit.MINUTES.toMillis(1) + TimeUnit.SECONDS.toMillis(1)));
|
||||||
|
assertThat(parser.parse("now+1m-1s", 0), equalTo(TimeUnit.MINUTES.toMillis(1) - TimeUnit.SECONDS.toMillis(1)));
|
||||||
|
|
||||||
|
assertThat(parser.parse("now+1m+1s/m", 0), equalTo(TimeUnit.MINUTES.toMillis(1)));
|
||||||
|
assertThat(parser.parseUpperInclusive("now+1m+1s/m", 0), equalTo(TimeUnit.MINUTES.toMillis(2)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void actualDateTests() {
|
||||||
|
DateMathParser parser = new DateMathParser(Joda.forPattern("dateOptionalTime"), TimeUnit.MILLISECONDS);
|
||||||
|
|
||||||
|
assertThat(parser.parse("1970-01-01", 0), equalTo(0l));
|
||||||
|
assertThat(parser.parse("1970-01-01||+1m", 0), equalTo(TimeUnit.MINUTES.toMillis(1)));
|
||||||
|
assertThat(parser.parse("1970-01-01||+1m+1s", 0), equalTo(TimeUnit.MINUTES.toMillis(1) + TimeUnit.SECONDS.toMillis(1)));
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue