Merge pull request #12693 from jpountz/enhancement/speed_up_function_score_query_when_replacing_score

Speed up the `function_score` query when scores are not needed.
This commit is contained in:
Adrien Grand 2015-08-06 15:14:44 +02:00
commit 8590fa49a6
8 changed files with 70 additions and 9 deletions

View File

@ -57,6 +57,11 @@ public class BoostScoreFunction extends ScoreFunction {
};
}
@Override
public boolean needsScores() {
return false;
}
@Override
public String toString() {
return "boost[" + boost + "]";

View File

@ -91,6 +91,11 @@ public class FieldValueFactorFunction extends ScoreFunction {
};
}
@Override
public boolean needsScores() {
return false;
}
/**
* The Type class encapsulates the modification types that can be applied
* to the score/value product.

View File

@ -44,7 +44,7 @@ public class FunctionScoreQuery extends Query {
public FunctionScoreQuery(Query subQuery, ScoreFunction function, Float minScore) {
this.subQuery = subQuery;
this.function = function;
this.combineFunction = function == null? combineFunction.MULT : function.getDefaultScoreCombiner();
this.combineFunction = function == null? CombineFunction.MULT : function.getDefaultScoreCombiner();
this.minScore = minScore;
}
@ -87,19 +87,27 @@ public class FunctionScoreQuery extends Query {
@Override
public Weight createWeight(IndexSearcher searcher, boolean needsScores) throws IOException {
// TODO: needsScores
// if we don't need scores, just return the underlying weight?
Weight subQueryWeight = subQuery.createWeight(searcher, needsScores);
return new CustomBoostFactorWeight(this, subQueryWeight);
if (needsScores == false) {
return subQuery.createWeight(searcher, needsScores);
}
boolean subQueryNeedsScores =
combineFunction != CombineFunction.REPLACE // if we don't replace we need the original score
|| function == null // when the function is null, we just multiply the score, so we need it
|| function.needsScores(); // some scripts can replace with a script that returns eg. 1/_score
Weight subQueryWeight = subQuery.createWeight(searcher, subQueryNeedsScores);
return new CustomBoostFactorWeight(this, subQueryWeight, subQueryNeedsScores);
}
class CustomBoostFactorWeight extends Weight {
final Weight subQueryWeight;
final boolean needsScores;
public CustomBoostFactorWeight(Query parent, Weight subQueryWeight) throws IOException {
public CustomBoostFactorWeight(Query parent, Weight subQueryWeight, boolean needsScores) throws IOException {
super(parent);
this.subQueryWeight = subQueryWeight;
this.needsScores = needsScores;
}
@Override
@ -129,7 +137,7 @@ public class FunctionScoreQuery extends Query {
if (function != null) {
leafFunction = function.getLeafScoreFunction(context);
}
return new FunctionFactorScorer(this, subQueryScorer, leafFunction, maxBoost, combineFunction, minScore);
return new FunctionFactorScorer(this, subQueryScorer, leafFunction, maxBoost, combineFunction, minScore, needsScores);
}
@Override
@ -150,16 +158,21 @@ public class FunctionScoreQuery extends Query {
static class FunctionFactorScorer extends CustomBoostFactorScorer {
private final LeafScoreFunction function;
private final boolean needsScores;
private FunctionFactorScorer(CustomBoostFactorWeight w, Scorer scorer, LeafScoreFunction function, float maxBoost, CombineFunction scoreCombiner, Float minScore)
private FunctionFactorScorer(CustomBoostFactorWeight w, Scorer scorer, LeafScoreFunction function, float maxBoost, CombineFunction scoreCombiner, Float minScore, boolean needsScores)
throws IOException {
super(w, scorer, maxBoost, scoreCombiner, minScore);
this.function = function;
this.needsScores = needsScores;
}
@Override
public float innerScore() throws IOException {
float score = scorer.score();
// Even if the weight is created with needsScores=false, it might
// be costly to call score(), so we explicitly check if scores
// are needed
float score = needsScores ? scorer.score() : 0f;
if (function == null) {
return subQueryBoost * score;
} else {

View File

@ -81,4 +81,8 @@ public class RandomScoreFunction extends ScoreFunction {
};
}
@Override
public boolean needsScores() {
return false;
}
}

View File

@ -39,4 +39,11 @@ public abstract class ScoreFunction {
}
public abstract LeafScoreFunction getLeafScoreFunction(LeafReaderContext ctx) throws IOException;
/**
* Indicates if document scores are needed by this function.
*
* @return {@code true} if scores are needed.
*/
public abstract boolean needsScores();
}

View File

@ -126,6 +126,13 @@ public class ScriptScoreFunction extends ScoreFunction {
};
}
@Override
public boolean needsScores() {
// Scripts might use _score so we return true here
// TODO: Make scripts able to tell us whether they use scores
return true;
}
@Override
public String toString() {
return "script" + sScript.toString();

View File

@ -71,6 +71,11 @@ public class WeightFactorFunction extends ScoreFunction {
};
}
@Override
public boolean needsScores() {
return false;
}
public Explanation explainWeight() {
return Explanation.match(getWeight(), "weight");
}
@ -99,5 +104,10 @@ public class WeightFactorFunction extends ScoreFunction {
}
};
}
@Override
public boolean needsScores() {
return false;
}
}
}

View File

@ -289,6 +289,11 @@ public abstract class DecayFunctionParser implements ScoreFunctionParser {
this.fieldData = fieldData;
}
@Override
public boolean needsScores() {
return false;
}
@Override
protected NumericDoubleValues distance(LeafReaderContext context) {
final MultiGeoPointValues geoPointValues = fieldData.load(context).getGeoPointValues();
@ -352,6 +357,11 @@ public abstract class DecayFunctionParser implements ScoreFunctionParser {
this.origin = origin;
}
@Override
public boolean needsScores() {
return false;
}
@Override
protected NumericDoubleValues distance(LeafReaderContext context) {
final SortedNumericDoubleValues doubleValues = fieldData.load(context).getDoubleValues();