FunctionScore should work on unampped fields when missing parameter is specified

This commit is contained in:
André Carvalho 2015-08-22 23:36:13 -03:00
parent febc7f5d4c
commit 345b2b98cf
3 changed files with 32 additions and 6 deletions

View File

@ -54,13 +54,24 @@ public class FieldValueFactorFunction extends ScoreFunction {
@Override @Override
public LeafScoreFunction getLeafScoreFunction(LeafReaderContext ctx) { 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() { return new LeafScoreFunction() {
@Override @Override
public double score(int docId, float subQueryScore) { public double score(int docId, float subQueryScore) {
values.setDocument(docId); final int numValues;
final int numValues = values.count(); if(values == null){
numValues = 0;
} else {
values.setDocument(docId);
numValues = values.count();
}
double value; double value;
if (numValues > 0) { if (numValues > 0) {
value = values.valueAt(0); value = values.valueAt(0);

View File

@ -19,11 +19,13 @@
package org.elasticsearch.index.query.functionscore.fieldvaluefactor; package org.elasticsearch.index.query.functionscore.fieldvaluefactor;
import org.apache.lucene.document.FieldType;
import org.elasticsearch.ElasticsearchException; import org.elasticsearch.ElasticsearchException;
import org.elasticsearch.common.lucene.search.function.FieldValueFactorFunction; import org.elasticsearch.common.lucene.search.function.FieldValueFactorFunction;
import org.elasticsearch.common.lucene.search.function.ScoreFunction; import org.elasticsearch.common.lucene.search.function.ScoreFunction;
import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.index.fielddata.IndexNumericFieldData; import org.elasticsearch.index.fielddata.IndexNumericFieldData;
import org.elasticsearch.index.fielddata.plain.DoubleArrayIndexFieldData;
import org.elasticsearch.index.mapper.FieldMapper; import org.elasticsearch.index.mapper.FieldMapper;
import org.elasticsearch.index.mapper.MappedFieldType; import org.elasticsearch.index.mapper.MappedFieldType;
import org.elasticsearch.index.query.QueryParseContext; import org.elasticsearch.index.query.QueryParseContext;
@ -86,11 +88,15 @@ public class FieldValueFactorFunctionParser implements ScoreFunctionParser {
SearchContext searchContext = SearchContext.current(); SearchContext searchContext = SearchContext.current();
MappedFieldType fieldType = searchContext.mapperService().smartNameFieldType(field); MappedFieldType fieldType = searchContext.mapperService().smartNameFieldType(field);
IndexNumericFieldData fieldData = null;
if (fieldType == 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, return new FieldValueFactorFunction(field, boostFactor, modifier, missing, fieldData);
(IndexNumericFieldData)searchContext.fieldData().getForField(fieldType));
} }
@Override @Override

View File

@ -104,6 +104,15 @@ public class FunctionScoreFieldValueIT extends ESIntegTestCase {
.get(); .get();
assertOrderedSearchHits(response, "1", "2", "3"); 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. // n divided by 0 is infinity, which should provoke an exception.
try { try {
response = client().prepareSearch("test") response = client().prepareSearch("test")