function_score: undo "Remove explanation of query score from functions"
This adds the Explanation to the explain score again. It is needed because the explanation of script functions will otherwise not contain an explanation of _score if boost mode is set to replace. closes #9826
This commit is contained in:
parent
e43f3a941b
commit
3add12a970
|
@ -53,7 +53,7 @@ public class BoostScoreFunction extends ScoreFunction {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Explanation explainScore(int docId, float subQueryScore) {
|
||||
public Explanation explainScore(int docId, Explanation subQueryScore) {
|
||||
Explanation exp = new Explanation(boost, "static boost factor");
|
||||
exp.addDetail(new Explanation(boost, "boostFactor"));
|
||||
return exp;
|
||||
|
|
|
@ -70,10 +70,10 @@ public class FieldValueFactorFunction extends ScoreFunction {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Explanation explainScore(int docId, float subQueryScore) {
|
||||
public Explanation explainScore(int docId, Explanation subQueryScore) {
|
||||
Explanation exp = new Explanation();
|
||||
String modifierStr = modifier != null ? modifier.toString() : "";
|
||||
double score = score(docId, subQueryScore);
|
||||
double score = score(docId, subQueryScore.getValue());
|
||||
exp.setValue(CombineFunction.toFloat(score));
|
||||
exp.setDescription("field value function: " +
|
||||
modifierStr + "(" + "doc['" + field + "'].value * factor=" + boostFactor + ")");
|
||||
|
|
|
@ -189,7 +189,7 @@ public class FiltersFunctionScoreQuery extends Query {
|
|||
filterFunction.filter.getDocIdSet(context, context.reader().getLiveDocs()));
|
||||
if (docSet.get(doc)) {
|
||||
filterFunction.function.setNextReader(context);
|
||||
Explanation functionExplanation = filterFunction.function.explainScore(doc, subQueryExpl.getValue());
|
||||
Explanation functionExplanation = filterFunction.function.explainScore(doc, subQueryExpl);
|
||||
double factor = functionExplanation.getValue();
|
||||
float sc = CombineFunction.toFloat(factor);
|
||||
ComplexExplanation filterExplanation = new ComplexExplanation(true, sc, "function score, product of:");
|
||||
|
|
|
@ -135,7 +135,7 @@ public class FunctionScoreQuery extends Query {
|
|||
return subQueryExpl;
|
||||
}
|
||||
function.setNextReader(context);
|
||||
Explanation functionExplanation = function.explainScore(doc, subQueryExpl.getValue());
|
||||
Explanation functionExplanation = function.explainScore(doc, subQueryExpl);
|
||||
return combineFunction.explain(getBoost(), subQueryExpl, functionExplanation, maxBoost);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -73,7 +73,7 @@ public class RandomScoreFunction extends ScoreFunction {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Explanation explainScore(int docId, float subQueryScore) {
|
||||
public Explanation explainScore(int docId, Explanation subQueryScore) {
|
||||
Explanation exp = new Explanation();
|
||||
exp.setDescription("random score function (seed: " + originalSeed + ")");
|
||||
return exp;
|
||||
|
|
|
@ -33,7 +33,7 @@ public abstract class ScoreFunction implements ReaderContextAware {
|
|||
|
||||
public abstract double score(int docId, float subQueryScore);
|
||||
|
||||
public abstract Explanation explainScore(int docId, float subQueryScore) throws IOException;
|
||||
public abstract Explanation explainScore(int docId, Explanation subQueryScore) throws IOException;
|
||||
|
||||
public CombineFunction getDefaultScoreCombiner() {
|
||||
return scoreCombiner;
|
||||
|
|
|
@ -107,20 +107,23 @@ public class ScriptScoreFunction extends ScoreFunction {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Explanation explainScore(int docId, float subQueryScore) throws IOException {
|
||||
public Explanation explainScore(int docId, Explanation subQueryScore) throws IOException {
|
||||
Explanation exp;
|
||||
if (script instanceof ExplainableSearchScript) {
|
||||
script.setNextDocId(docId);
|
||||
scorer.docid = docId;
|
||||
scorer.score = subQueryScore;
|
||||
scorer.score = subQueryScore.getValue();
|
||||
exp = ((ExplainableSearchScript) script).explain(subQueryScore);
|
||||
} else {
|
||||
double score = score(docId, subQueryScore);
|
||||
double score = score(docId, subQueryScore.getValue());
|
||||
String explanation = "script score function, computed with script:\"" + sScript;
|
||||
if (params != null) {
|
||||
explanation += "\" and parameters: \n" + params.toString();
|
||||
}
|
||||
exp = new Explanation(CombineFunction.toFloat(score), explanation);
|
||||
Explanation scoreExp = new Explanation(subQueryScore.getValue(), "_score: ");
|
||||
scoreExp.addDetail(subQueryScore);
|
||||
exp.addDetail(scoreExp);
|
||||
}
|
||||
return exp;
|
||||
}
|
||||
|
|
|
@ -65,9 +65,9 @@ public class WeightFactorFunction extends ScoreFunction {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Explanation explainScore(int docId, float score) throws IOException {
|
||||
public Explanation explainScore(int docId, Explanation subQueryScore) throws IOException {
|
||||
Explanation functionScoreExplanation;
|
||||
Explanation functionExplanation = scoreFunction.explainScore(docId, score);
|
||||
Explanation functionExplanation = scoreFunction.explainScore(docId, subQueryScore);
|
||||
functionScoreExplanation = new ComplexExplanation(true, functionExplanation.getValue() * (float) getWeight(), "product of:");
|
||||
functionScoreExplanation.addDetail(functionExplanation);
|
||||
functionScoreExplanation.addDetail(explainWeight());
|
||||
|
@ -99,7 +99,7 @@ public class WeightFactorFunction extends ScoreFunction {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Explanation explainScore(int docId, float subQueryScore) {
|
||||
public Explanation explainScore(int docId, Explanation subQueryScore) {
|
||||
return new Explanation(1.0f, "constant score 1.0 - no function provided");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -456,9 +456,9 @@ public abstract class DecayFunctionParser implements ScoreFunctionParser {
|
|||
protected abstract String getFieldName();
|
||||
|
||||
@Override
|
||||
public Explanation explainScore(int docId, float subQueryScore) {
|
||||
public Explanation explainScore(int docId, Explanation subQueryScore) {
|
||||
ComplexExplanation ce = new ComplexExplanation();
|
||||
ce.setValue(CombineFunction.toFloat(score(docId, subQueryScore)));
|
||||
ce.setValue(CombineFunction.toFloat(score(docId, subQueryScore.getValue())));
|
||||
ce.setMatch(true);
|
||||
ce.setDescription("Function for field " + getFieldName() + ":");
|
||||
ce.addDetail(func.explainFunction(getDistanceString(docId), distance(docId), scale));
|
||||
|
|
|
@ -51,9 +51,11 @@ public interface ExplainableSearchScript extends SearchScript {
|
|||
|
||||
/**
|
||||
* Build the explanation of the current document being scored
|
||||
* The script score needs the Explanation of the sub query score because it might use _score and
|
||||
* want to explain how that was computed.
|
||||
*
|
||||
* @param score the score
|
||||
* @param subQueryScore the Explanation for _score
|
||||
*/
|
||||
Explanation explain(float score) throws IOException;
|
||||
Explanation explain(Explanation subQueryScore) throws IOException;
|
||||
|
||||
}
|
|
@ -24,6 +24,7 @@ import org.elasticsearch.action.index.IndexRequestBuilder;
|
|||
import org.elasticsearch.action.search.SearchResponse;
|
||||
import org.elasticsearch.action.search.SearchType;
|
||||
import org.elasticsearch.common.Nullable;
|
||||
import org.elasticsearch.common.lucene.search.function.CombineFunction;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.index.fielddata.ScriptDocValues;
|
||||
import org.elasticsearch.script.AbstractDoubleSearchScript;
|
||||
|
@ -47,6 +48,7 @@ import static org.elasticsearch.common.settings.ImmutableSettings.settingsBuilde
|
|||
import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
|
||||
import static org.elasticsearch.index.query.FilterBuilders.termFilter;
|
||||
import static org.elasticsearch.index.query.QueryBuilders.functionScoreQuery;
|
||||
import static org.elasticsearch.index.query.QueryBuilders.termQuery;
|
||||
import static org.elasticsearch.index.query.functionscore.ScoreFunctionBuilders.scriptFunction;
|
||||
import static org.elasticsearch.search.builder.SearchSourceBuilder.searchSource;
|
||||
import static org.elasticsearch.test.ElasticsearchIntegrationTest.ClusterScope;
|
||||
|
@ -77,7 +79,7 @@ public class ExplainableScriptTests extends ElasticsearchIntegrationTest {
|
|||
client().admin().indices().prepareRefresh().execute().actionGet();
|
||||
ensureYellow();
|
||||
SearchResponse response = client().search(searchRequest().searchType(SearchType.QUERY_THEN_FETCH).source(
|
||||
searchSource().explain(true).query(functionScoreQuery(termFilter("text", "text")).add(scriptFunction("native_explainable_script", "native")).boostMode("sum")))).actionGet();
|
||||
searchSource().explain(true).query(functionScoreQuery(termQuery("text", "text")).add(scriptFunction("native_explainable_script", "native")).boostMode("replace")))).actionGet();
|
||||
|
||||
ElasticsearchAssertions.assertNoFailures(response);
|
||||
SearchHits hits = response.getHits();
|
||||
|
@ -86,6 +88,8 @@ public class ExplainableScriptTests extends ElasticsearchIntegrationTest {
|
|||
for (SearchHit hit : hits.getHits()) {
|
||||
assertThat(hit.getId(), equalTo(Integer.toString(idCounter)));
|
||||
assertThat(hit.explanation().toString(), containsString(Double.toString(idCounter) + " = This script returned " + Double.toString(idCounter)));
|
||||
assertThat(hit.explanation().toString(), containsString("1.0 = tf(freq=1.0), with freq of"));
|
||||
assertThat(hit.explanation().getDetails().length, equalTo(2));
|
||||
idCounter--;
|
||||
}
|
||||
}
|
||||
|
@ -105,8 +109,12 @@ public class ExplainableScriptTests extends ElasticsearchIntegrationTest {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Explanation explain(float score) throws IOException {
|
||||
return new Explanation((float) (runAsDouble()), "This script returned " + runAsDouble());
|
||||
public Explanation explain(Explanation subQueryScore) throws IOException {
|
||||
Explanation exp = new Explanation((float) (runAsDouble()), "This script returned " + runAsDouble());
|
||||
Explanation scoreExp = new Explanation(subQueryScore.getValue(), "_score: ");
|
||||
scoreExp.addDetail(subQueryScore);
|
||||
exp.addDetail(scoreExp);
|
||||
return exp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -177,7 +177,7 @@ public class FunctionScoreTests extends ElasticsearchIntegrationTest {
|
|||
).explain(true))).actionGet();
|
||||
|
||||
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")
|
||||
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 1.0 = _score: \n 1.0 = (MATCH) ConstantScore(text_field:value), product of:\n 1.0 = boost\n 1.0 = queryNorm\n 3.0 = weight\n 3.4028235E38 = maxBoost\n 1.0 = queryBoost\n")
|
||||
);
|
||||
responseWithWeights = client().search(
|
||||
searchRequest().source(
|
||||
|
|
Loading…
Reference in New Issue