From 345b2b98cfa5af1900b65ba62835f64af025fbea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Carvalho?= Date: Sat, 22 Aug 2015 23:36:13 -0300 Subject: [PATCH] FunctionScore should work on unampped fields when missing parameter is specified --- .../function/FieldValueFactorFunction.java | 17 ++++++++++++++--- .../FieldValueFactorFunctionParser.java | 12 +++++++++--- .../FunctionScoreFieldValueIT.java | 9 +++++++++ 3 files changed, 32 insertions(+), 6 deletions(-) diff --git a/core/src/main/java/org/elasticsearch/common/lucene/search/function/FieldValueFactorFunction.java b/core/src/main/java/org/elasticsearch/common/lucene/search/function/FieldValueFactorFunction.java index 488c5fec603..e6d1362f9e7 100644 --- a/core/src/main/java/org/elasticsearch/common/lucene/search/function/FieldValueFactorFunction.java +++ b/core/src/main/java/org/elasticsearch/common/lucene/search/function/FieldValueFactorFunction.java @@ -54,13 +54,24 @@ public class FieldValueFactorFunction extends ScoreFunction { @Override public LeafScoreFunction getLeafScoreFunction(LeafReaderContext ctx) { - final SortedNumericDoubleValues values = this.indexFieldData.load(ctx).getDoubleValues(); + final SortedNumericDoubleValues values; + if(indexFieldData == null) { + values = null; + } else { + values = this.indexFieldData.load(ctx).getDoubleValues(); + } + return new LeafScoreFunction() { @Override public double score(int docId, float subQueryScore) { - values.setDocument(docId); - final int numValues = values.count(); + final int numValues; + if(values == null){ + numValues = 0; + } else { + values.setDocument(docId); + numValues = values.count(); + } double value; if (numValues > 0) { value = values.valueAt(0); diff --git a/core/src/main/java/org/elasticsearch/index/query/functionscore/fieldvaluefactor/FieldValueFactorFunctionParser.java b/core/src/main/java/org/elasticsearch/index/query/functionscore/fieldvaluefactor/FieldValueFactorFunctionParser.java index e6a8f2dabcc..6f68db58aca 100644 --- a/core/src/main/java/org/elasticsearch/index/query/functionscore/fieldvaluefactor/FieldValueFactorFunctionParser.java +++ b/core/src/main/java/org/elasticsearch/index/query/functionscore/fieldvaluefactor/FieldValueFactorFunctionParser.java @@ -19,11 +19,13 @@ package org.elasticsearch.index.query.functionscore.fieldvaluefactor; +import org.apache.lucene.document.FieldType; import org.elasticsearch.ElasticsearchException; import org.elasticsearch.common.lucene.search.function.FieldValueFactorFunction; import org.elasticsearch.common.lucene.search.function.ScoreFunction; import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.index.fielddata.IndexNumericFieldData; +import org.elasticsearch.index.fielddata.plain.DoubleArrayIndexFieldData; import org.elasticsearch.index.mapper.FieldMapper; import org.elasticsearch.index.mapper.MappedFieldType; import org.elasticsearch.index.query.QueryParseContext; @@ -86,11 +88,15 @@ public class FieldValueFactorFunctionParser implements ScoreFunctionParser { SearchContext searchContext = SearchContext.current(); MappedFieldType fieldType = searchContext.mapperService().smartNameFieldType(field); + IndexNumericFieldData fieldData = null; if (fieldType == null) { - throw new ElasticsearchException("Unable to find a field mapper for field [" + field + "]"); + if(missing == null) { + throw new ElasticsearchException("Unable to find a field mapper for field [" + field + "]. No 'missing' value defined."); + } + } else { + fieldData = searchContext.fieldData().getForField(fieldType); } - return new FieldValueFactorFunction(field, boostFactor, modifier, missing, - (IndexNumericFieldData)searchContext.fieldData().getForField(fieldType)); + return new FieldValueFactorFunction(field, boostFactor, modifier, missing, fieldData); } @Override diff --git a/core/src/test/java/org/elasticsearch/search/functionscore/FunctionScoreFieldValueIT.java b/core/src/test/java/org/elasticsearch/search/functionscore/FunctionScoreFieldValueIT.java index 577b3eaea31..24d06701b40 100644 --- a/core/src/test/java/org/elasticsearch/search/functionscore/FunctionScoreFieldValueIT.java +++ b/core/src/test/java/org/elasticsearch/search/functionscore/FunctionScoreFieldValueIT.java @@ -104,6 +104,15 @@ public class FunctionScoreFieldValueIT extends ESIntegTestCase { .get(); assertOrderedSearchHits(response, "1", "2", "3"); + // field is not mapped but we're defaulting it to 100 so all documents should have the same score + response = client().prepareSearch("test") + .setExplain(randomBoolean()) + .setQuery(functionScoreQuery(matchAllQuery(), + fieldValueFactorFunction("notmapped").modifier(FieldValueFactorFunction.Modifier.RECIPROCAL).missing(100))) + .get(); + assertEquals(response.getHits().getAt(0).score(), response.getHits().getAt(2).score(), 0); + + // n divided by 0 is infinity, which should provoke an exception. try { response = client().prepareSearch("test")