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 1/3] 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") From 60ab72e32246cd301b194faaebff91f7c25ef6a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Carvalho?= Date: Mon, 24 Aug 2015 09:19:45 -0300 Subject: [PATCH 2/3] using emptySortedNumericDoubles instead of null in score function --- .../search/function/FieldValueFactorFunction.java | 12 ++++-------- 1 file changed, 4 insertions(+), 8 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 e6d1362f9e7..38c2cc98a2e 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 @@ -22,6 +22,7 @@ package org.elasticsearch.common.lucene.search.function; import org.apache.lucene.index.LeafReaderContext; import org.apache.lucene.search.Explanation; import org.elasticsearch.ElasticsearchException; +import org.elasticsearch.index.fielddata.FieldData; import org.elasticsearch.index.fielddata.IndexNumericFieldData; import org.elasticsearch.index.fielddata.SortedNumericDoubleValues; @@ -56,7 +57,7 @@ public class FieldValueFactorFunction extends ScoreFunction { public LeafScoreFunction getLeafScoreFunction(LeafReaderContext ctx) { final SortedNumericDoubleValues values; if(indexFieldData == null) { - values = null; + values = FieldData.emptySortedNumericDoubles(0); } else { values = this.indexFieldData.load(ctx).getDoubleValues(); } @@ -65,13 +66,8 @@ public class FieldValueFactorFunction extends ScoreFunction { @Override public double score(int docId, float subQueryScore) { - final int numValues; - if(values == null){ - numValues = 0; - } else { - values.setDocument(docId); - numValues = values.count(); - } + values.setDocument(docId); + final int numValues = values.count(); double value; if (numValues > 0) { value = values.valueAt(0); From c2c4742f6543991dc06f106b45d96f3a03eb4e7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Carvalho?= Date: Mon, 24 Aug 2015 10:02:18 -0300 Subject: [PATCH 3/3] proper creation of values for unmapped field on score function --- .../common/lucene/search/function/FieldValueFactorFunction.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 38c2cc98a2e..cb2babb574f 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 @@ -57,7 +57,7 @@ public class FieldValueFactorFunction extends ScoreFunction { public LeafScoreFunction getLeafScoreFunction(LeafReaderContext ctx) { final SortedNumericDoubleValues values; if(indexFieldData == null) { - values = FieldData.emptySortedNumericDoubles(0); + values = FieldData.emptySortedNumericDoubles(ctx.reader().maxDoc()); } else { values = this.indexFieldData.load(ctx).getDoubleValues(); }