Support date math for `origin` decay function parsing

The parser used the method that was supposed to be used for parsing on
the indexing side that never supported date math.

Closes #3892
This commit is contained in:
Simon Willnauer 2013-10-11 14:41:38 +02:00
parent ef26df4f42
commit 2d523ace87
3 changed files with 58 additions and 25 deletions

View File

@ -294,44 +294,48 @@ public class DateFieldMapper extends NumberFieldMapper<Long> {
@Override
public Query termQuery(Object value, @Nullable QueryParseContext context) {
long now = context == null ? System.currentTimeMillis() : context.nowInMillis();
long lValue = dateMathParser.parse(convertToString(value), now);
long lValue = parseToMilliseconds(value, context);
return NumericRangeQuery.newLongRange(names.indexName(), precisionStep,
lValue, lValue, true, true);
}
public long parseToMilliseconds(Object value, @Nullable QueryParseContext context) {
return parseToMilliseconds(value, context, false);
}
public long parseToMilliseconds(Object value, @Nullable QueryParseContext context, boolean includeUpper) {
long now = context == null ? System.currentTimeMillis() : context.nowInMillis();
return includeUpper ? dateMathParser.parseUpperInclusive(convertToString(value), now) : dateMathParser.parse(convertToString(value), now);
}
@Override
public Filter termFilter(Object value, @Nullable QueryParseContext context) {
long now = context == null ? System.currentTimeMillis() : context.nowInMillis();
long lValue = dateMathParser.parse(convertToString(value), now);
final long lValue = parseToMilliseconds(value, context);
return NumericRangeFilter.newLongRange(names.indexName(), precisionStep,
lValue, lValue, true, true);
}
@Override
public Query rangeQuery(Object lowerTerm, Object upperTerm, boolean includeLower, boolean includeUpper, @Nullable QueryParseContext context) {
long now = context == null ? System.currentTimeMillis() : context.nowInMillis();
return NumericRangeQuery.newLongRange(names.indexName(), precisionStep,
lowerTerm == null ? null : dateMathParser.parse(convertToString(lowerTerm), now),
upperTerm == null ? null : (includeUpper && parseUpperInclusive) ? dateMathParser.parseUpperInclusive(convertToString(upperTerm), now) : dateMathParser.parse(convertToString(upperTerm), now),
lowerTerm == null ? null : parseToMilliseconds(lowerTerm, context),
upperTerm == null ? null : parseToMilliseconds(upperTerm, context, includeUpper && parseUpperInclusive),
includeLower, includeUpper);
}
@Override
public Filter rangeFilter(Object lowerTerm, Object upperTerm, boolean includeLower, boolean includeUpper, @Nullable QueryParseContext context) {
long now = context == null ? System.currentTimeMillis() : context.nowInMillis();
return NumericRangeFilter.newLongRange(names.indexName(), precisionStep,
lowerTerm == null ? null : dateMathParser.parse(convertToString(lowerTerm), now),
upperTerm == null ? null : (includeUpper && parseUpperInclusive) ? dateMathParser.parseUpperInclusive(convertToString(upperTerm), now) : dateMathParser.parse(convertToString(upperTerm), now),
lowerTerm == null ? null : parseToMilliseconds(lowerTerm, context),
upperTerm == null ? null : parseToMilliseconds(upperTerm, context, includeUpper && parseUpperInclusive),
includeLower, includeUpper);
}
@Override
public Filter rangeFilter(IndexFieldDataService fieldData, Object lowerTerm, Object upperTerm, boolean includeLower, boolean includeUpper, @Nullable QueryParseContext context) {
long now = context == null ? System.currentTimeMillis() : context.nowInMillis();
return NumericRangeFieldDataFilter.newLongRange((IndexNumericFieldData<?>) fieldData.getForField(this),
lowerTerm == null ? null : dateMathParser.parse(convertToString(lowerTerm), now),
upperTerm == null ? null : (includeUpper && parseUpperInclusive) ? dateMathParser.parseUpperInclusive(convertToString(upperTerm), now) : dateMathParser.parse(convertToString(upperTerm), now),
lowerTerm == null ? null : parseToMilliseconds(lowerTerm, context),
upperTerm == null ? null : parseToMilliseconds(upperTerm, context, includeUpper && parseUpperInclusive),
includeLower, includeUpper);
}

View File

@ -250,11 +250,11 @@ public abstract class DecayFunctionParser implements ScoreFunctionParser {
}
long origin = SearchContext.current().nowInMillis();
if (originString != null) {
origin = dateFieldMapper.value(originString).longValue();
origin = dateFieldMapper.parseToMilliseconds(originString, parseContext);
}
if (scaleString == null) {
throw new ElasticSearchParseException(DecayFunctionBuilder.SCALE + "must be set for date fields.");
throw new ElasticSearchParseException(DecayFunctionBuilder.SCALE + " must be set for date fields.");
}
TimeValue val = TimeValue.parseTimeValue(scaleString, TimeValue.timeValueHours(24));
double scale = val.getMillis();

View File

@ -33,7 +33,6 @@ import org.elasticsearch.index.query.functionscore.DecayFunctionBuilder;
import org.elasticsearch.index.query.functionscore.gauss.GaussDecayFunctionBuilder;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.test.AbstractIntegrationTest;
import org.elasticsearch.test.hamcrest.ElasticSearchAssertions;
import org.joda.time.DateTime;
import org.junit.Test;
@ -47,7 +46,7 @@ import static org.elasticsearch.index.query.QueryBuilders.functionScoreQuery;
import static org.elasticsearch.index.query.QueryBuilders.termQuery;
import static org.elasticsearch.index.query.functionscore.ScoreFunctionBuilders.*;
import static org.elasticsearch.search.builder.SearchSourceBuilder.searchSource;
import static org.elasticsearch.test.hamcrest.ElasticSearchAssertions.assertAcked;
import static org.elasticsearch.test.hamcrest.ElasticSearchAssertions.*;
import static org.hamcrest.Matchers.*;
public class DecayFunctionScoreTests extends AbstractIntegrationTest {
@ -450,14 +449,44 @@ public class DecayFunctionScoreTests extends AbstractIntegrationTest {
functionScoreQuery(termQuery("test", "value"), gaussDecayFunction("num1", "2013-05-28", "-1d")))));
SearchResponse sr = response.actionGet();
ElasticSearchAssertions.assertNoFailures(sr);
SearchHits sh = sr.getHits();
assertThat(sh.hits().length, equalTo(2));
assertThat(sh.getAt(0).getId(), equalTo("2"));
assertThat(sh.getAt(1).getId(), equalTo("1"));
assertOrderedSearchHits(sr, "2", "1");
}
@Test
public void testParseDateMath() throws Exception {
assertAcked(prepareCreate("test").addMapping(
"type1",
jsonBuilder().startObject().startObject("type1").startObject("properties").startObject("test").field("type", "string")
.endObject().startObject("num1").field("type", "date").endObject().endObject().endObject().endObject()));
ensureYellow();
client().index(
indexRequest("test").type("type1").id("1")
.source(jsonBuilder().startObject().field("test", "value").field("num1", System.currentTimeMillis()).endObject())).actionGet();
client().index(
indexRequest("test").type("type1").id("2")
.source(jsonBuilder().startObject().field("test", "value").field("num1", System.currentTimeMillis() - (1000 * 60 * 60 * 24)).endObject())).actionGet();
refresh();
SearchResponse sr = client().search(
searchRequest().source(
searchSource().explain(true).query(
functionScoreQuery(termQuery("test", "value"), gaussDecayFunction("num1", "now", "2d"))))).get();
assertNoFailures(sr);
assertOrderedSearchHits(sr, "1", "2");
sr = client().search(
searchRequest().source(
searchSource().explain(true).query(
functionScoreQuery(termQuery("test", "value"), gaussDecayFunction("num1", "now-1d", "2d"))))).get();
assertNoFailures(sr);
assertOrderedSearchHits(sr, "2", "1");
}
@Test(expected = ElasticSearchIllegalStateException.class)
public void testExceptionThrownIfScaleRefNotBetween0And1() throws Exception {
DecayFunctionBuilder gfb = new GaussDecayFunctionBuilder("num1", "2013-05-28", "1d").setDecay(100);
@ -501,7 +530,7 @@ public class DecayFunctionScoreTests extends AbstractIntegrationTest {
.add(linearDecayFunction("num2", "0.0", "1")).scoreMode("multiply"))));
SearchResponse sr = response.actionGet();
ElasticSearchAssertions.assertNoFailures(sr);
assertNoFailures(sr);
SearchHits sh = sr.getHits();
assertThat(sh.hits().length, equalTo(4));
double[] scores = new double[4];
@ -549,7 +578,7 @@ public class DecayFunctionScoreTests extends AbstractIntegrationTest {
.scoreMode("multiply"))));
SearchResponse sr = response.actionGet();
ElasticSearchAssertions.assertNoFailures(sr);
assertNoFailures(sr);
SearchHits sh = sr.getHits();
assertThat(sh.hits().length, equalTo(3));
double[] scores = new double[4];
@ -602,7 +631,7 @@ public class DecayFunctionScoreTests extends AbstractIntegrationTest {
.scoreMode("multiply").boostMode(CombineFunction.REPLACE.getName()))));
SearchResponse sr = response.actionGet();
ElasticSearchAssertions.assertNoFailures(sr);
assertNoFailures(sr);
SearchHits sh = sr.getHits();
assertThat(sh.hits().length, equalTo(numDocs));
double[] scores = new double[numDocs];