Only compute scores when necessary with FiltersFunctionScoreQuery.

This was just done with FunctionScoreQuery, but FiltersFunctionScoreQuery works
in a similar way.
This commit is contained in:
Adrien Grand 2015-08-06 21:42:46 +02:00
parent 4bde564ab9
commit 5cad559914
1 changed files with 19 additions and 8 deletions

View File

@ -124,25 +124,31 @@ public class FiltersFunctionScoreQuery extends Query {
@Override @Override
public Weight createWeight(IndexSearcher searcher, boolean needsScores) throws IOException { public Weight createWeight(IndexSearcher searcher, boolean needsScores) throws IOException {
// TODO: needsScores if (needsScores == false) {
// if we dont need scores, just return the underlying Weight? return subQuery.createWeight(searcher, needsScores);
Weight subQueryWeight = subQuery.createWeight(searcher, needsScores); }
boolean subQueryNeedsScores = combineFunction != CombineFunction.REPLACE;
Weight[] filterWeights = new Weight[filterFunctions.length]; Weight[] filterWeights = new Weight[filterFunctions.length];
for (int i = 0; i < filterFunctions.length; ++i) { for (int i = 0; i < filterFunctions.length; ++i) {
subQueryNeedsScores |= filterFunctions[i].function.needsScores();
filterWeights[i] = searcher.createNormalizedWeight(filterFunctions[i].filter, false); filterWeights[i] = searcher.createNormalizedWeight(filterFunctions[i].filter, false);
} }
return new CustomBoostFactorWeight(this, subQueryWeight, filterWeights); Weight subQueryWeight = subQuery.createWeight(searcher, subQueryNeedsScores);
return new CustomBoostFactorWeight(this, subQueryWeight, filterWeights, subQueryNeedsScores);
} }
class CustomBoostFactorWeight extends Weight { class CustomBoostFactorWeight extends Weight {
final Weight subQueryWeight; final Weight subQueryWeight;
final Weight[] filterWeights; final Weight[] filterWeights;
final boolean needsScores;
public CustomBoostFactorWeight(Query parent, Weight subQueryWeight, Weight[] filterWeights) throws IOException { public CustomBoostFactorWeight(Query parent, Weight subQueryWeight, Weight[] filterWeights, boolean needsScores) throws IOException {
super(parent); super(parent);
this.subQueryWeight = subQueryWeight; this.subQueryWeight = subQueryWeight;
this.filterWeights = filterWeights; this.filterWeights = filterWeights;
this.needsScores = needsScores;
} }
@Override @Override
@ -179,7 +185,7 @@ public class FiltersFunctionScoreQuery extends Query {
Scorer filterScorer = filterWeights[i].scorer(context, null); // no need to apply accepted docs Scorer filterScorer = filterWeights[i].scorer(context, null); // no need to apply accepted docs
docSets[i] = Lucene.asSequentialAccessBits(context.reader().maxDoc(), filterScorer); docSets[i] = Lucene.asSequentialAccessBits(context.reader().maxDoc(), filterScorer);
} }
return new FiltersFunctionFactorScorer(this, subQueryScorer, scoreMode, filterFunctions, maxBoost, functions, docSets, combineFunction, minScore); return new FiltersFunctionFactorScorer(this, subQueryScorer, scoreMode, filterFunctions, maxBoost, functions, docSets, combineFunction, minScore, needsScores);
} }
@Override @Override
@ -269,21 +275,26 @@ public class FiltersFunctionScoreQuery extends Query {
private final ScoreMode scoreMode; private final ScoreMode scoreMode;
private final LeafScoreFunction[] functions; private final LeafScoreFunction[] functions;
private final Bits[] docSets; private final Bits[] docSets;
private final boolean needsScores;
private FiltersFunctionFactorScorer(CustomBoostFactorWeight w, Scorer scorer, ScoreMode scoreMode, FilterFunction[] filterFunctions, private FiltersFunctionFactorScorer(CustomBoostFactorWeight w, Scorer scorer, ScoreMode scoreMode, FilterFunction[] filterFunctions,
float maxBoost, LeafScoreFunction[] functions, Bits[] docSets, CombineFunction scoreCombiner, Float minScore) throws IOException { float maxBoost, LeafScoreFunction[] functions, Bits[] docSets, CombineFunction scoreCombiner, Float minScore, boolean needsScores) throws IOException {
super(w, scorer, maxBoost, scoreCombiner, minScore); super(w, scorer, maxBoost, scoreCombiner, minScore);
this.scoreMode = scoreMode; this.scoreMode = scoreMode;
this.filterFunctions = filterFunctions; this.filterFunctions = filterFunctions;
this.functions = functions; this.functions = functions;
this.docSets = docSets; this.docSets = docSets;
this.needsScores = needsScores;
} }
@Override @Override
public float innerScore() throws IOException { public float innerScore() throws IOException {
int docId = scorer.docID(); int docId = scorer.docID();
double factor = 1.0f; double factor = 1.0f;
float subQueryScore = 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 subQueryScore = needsScores ? scorer.score() : 0f;
if (scoreMode == ScoreMode.First) { if (scoreMode == ScoreMode.First) {
for (int i = 0; i < filterFunctions.length; i++) { for (int i = 0; i < filterFunctions.length; i++) {
if (docSets[i].get(docId)) { if (docSets[i].get(docId)) {