Scripting: Add explicit error message when script_score script returns NaN
When a scoring script returns not a number, the current message is confusing (IllegalArgumentException[docID must be >= 0 and < maxDoc=3 (got docID=2147483647)]). This commit adds the error message ScriptException[script score function returns a wrong score: NaN]. Closes #2426
This commit is contained in:
parent
7b64a5c2c8
commit
a046ee756d
|
@ -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.apache.lucene.search.Scorer;
|
||||
import org.elasticsearch.script.ScriptException;
|
||||
import org.elasticsearch.script.SearchScript;
|
||||
|
||||
import java.io.IOException;
|
||||
|
@ -96,7 +97,11 @@ public class ScriptScoreFunction extends ScoreFunction {
|
|||
script.setNextDocId(docId);
|
||||
scorer.docid = docId;
|
||||
scorer.score = subQueryScore;
|
||||
return script.runAsDouble();
|
||||
double result = script.runAsDouble();
|
||||
if (Double.isNaN(result)) {
|
||||
throw new ScriptException("script_score returned NaN");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package org.elasticsearch.common.lucene.search.function;
|
||||
|
||||
import org.elasticsearch.script.AbstractFloatSearchScript;
|
||||
import org.elasticsearch.script.ScriptException;
|
||||
import org.elasticsearch.test.ElasticsearchTestCase;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
|
||||
public class ScriptScoreFunctionTests extends ElasticsearchTestCase {
|
||||
|
||||
/**
|
||||
* Tests https://github.com/elasticsearch/elasticsearch/issues/2426
|
||||
*/
|
||||
@Test
|
||||
public void testScriptScoresReturnsNaN() {
|
||||
try {
|
||||
ScoreFunction scoreFunction = new ScriptScoreFunction("Float.NaN", null, new FloatValueScript(Float.NaN));
|
||||
scoreFunction.score(randomInt(), randomFloat());
|
||||
fail("should have thrown an exception about the script_score returning NaN");
|
||||
} catch (ScriptException e) {
|
||||
assertThat("message contains error about script_score returning NaN: " + e.getMessage(),
|
||||
e.getMessage().contains("NaN"), equalTo(true));
|
||||
}
|
||||
}
|
||||
|
||||
static class FloatValueScript extends AbstractFloatSearchScript {
|
||||
|
||||
private final float value;
|
||||
|
||||
FloatValueScript(float value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float runAsFloat() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setNextDocId(int doc) {
|
||||
// nothing here
|
||||
}
|
||||
}
|
||||
}
|
|
@ -169,7 +169,7 @@ public class FunctionScoreTests extends ElasticsearchIntegrationTest {
|
|||
|
||||
assertThat(responseWithWeights.getHits().getAt(0).getExplanation().toString(),
|
||||
equalTo("6.0 = (MATCH) function score, product of:\n 1.0 = (MATCH) ConstantScore(text_field:value), product of:\n 1.0 = boost\n 1.0 = queryNorm\n 6.0 = (MATCH) Math.min of\n 6.0 = (MATCH) function score, score mode [multiply]\n 1.0 = (MATCH) function score, product of:\n 1.0 = match filter: *:*\n 1.0 = (MATCH) Function for field geo_point_field:\n 1.0 = exp(-0.5*pow(MIN of: [Math.max(arcDistance([10.0, 20.0](=doc value),[10.0, 20.0](=origin)) - 0.0(=offset), 0)],2.0)/7.213475204444817E11)\n 2.0 = (MATCH) function score, product of:\n 1.0 = match filter: *:*\n 2.0 = (MATCH) product of:\n 1.0 = field value function: ln(doc['double_field'].value * factor=1.0)\n 2.0 = weight\n 3.0 = (MATCH) function score, product of:\n 1.0 = match filter: *:*\n 3.0 = (MATCH) product of:\n 1.0 = script score function, computed with script:\"_index['text_field']['value'].tf()\n 3.0 = weight\n 3.4028235E38 = maxBoost\n 1.0 = queryBoost\n")
|
||||
);
|
||||
);
|
||||
responseWithWeights = client().search(
|
||||
searchRequest().source(
|
||||
searchSource().query(
|
||||
|
|
Loading…
Reference in New Issue