mirror of https://github.com/apache/lucene.git
Fix MaxScoreBulkScorer#score's return value. (#12400)
`AssertingBulkScorer` asserts that the return value of `BulkScorer#score` may not be in `[maxDoc, NO_MORE_DOCS)`. While this is not part of the contract of `BulkScorer#score`, a reasonable implementation should never have return values in this range, as it would suggest that more matches need collecting when we're already out of the range of valid doc IDs. So this generally indicates a bug. `MaxScoreBulkScorer` failed this assertion, because it can sometimes skip the requested window of doc IDs, when the sum of maximum scores would be less than the minimum competitive score. In that case, the best information it has is that there are no matches in the window, but it cannot give a good estimate of the next potential match. This assertion in `AssertingBulkScorer` looks sane to me, so I made a small change to `MaxScoreBulkScorer` to make sure it meets `AssertingScorer`'s expectations. This is done in a place that is only called once per scored window, so it should not have a noticeable performance impact.
This commit is contained in:
parent
6bb8cc0235
commit
4029cc37a7
|
@ -218,7 +218,7 @@ final class BooleanWeight extends Weight {
|
|||
optionalScorers.add(ss.get(Long.MAX_VALUE));
|
||||
}
|
||||
|
||||
return new MaxScoreBulkScorer(optionalScorers);
|
||||
return new MaxScoreBulkScorer(context.reader().maxDoc(), optionalScorers);
|
||||
}
|
||||
|
||||
List<BulkScorer> optional = new ArrayList<BulkScorer>();
|
||||
|
|
|
@ -24,6 +24,7 @@ import org.apache.lucene.util.Bits;
|
|||
|
||||
final class MaxScoreBulkScorer extends BulkScorer {
|
||||
|
||||
private final int maxDoc;
|
||||
// All scorers, sorted by increasing max score.
|
||||
private final DisiWrapper[] allScorers;
|
||||
// These are the last scorers from `allScorers` that are "essential", ie. required for a match to
|
||||
|
@ -39,7 +40,8 @@ final class MaxScoreBulkScorer extends BulkScorer {
|
|||
private ScoreAndDoc scorable = new ScoreAndDoc();
|
||||
private final double[] maxScoreSums;
|
||||
|
||||
MaxScoreBulkScorer(List<Scorer> scorers) throws IOException {
|
||||
MaxScoreBulkScorer(int maxDoc, List<Scorer> scorers) throws IOException {
|
||||
this.maxDoc = maxDoc;
|
||||
allScorers = new DisiWrapper[scorers.size()];
|
||||
int i = 0;
|
||||
long cost = 0;
|
||||
|
@ -181,6 +183,10 @@ final class MaxScoreBulkScorer extends BulkScorer {
|
|||
|
||||
/** Return the next candidate on or after {@code rangeEnd}. */
|
||||
private int nextCandidate(int rangeEnd) {
|
||||
if (rangeEnd >= maxDoc) {
|
||||
return DocIdSetIterator.NO_MORE_DOCS;
|
||||
}
|
||||
|
||||
int next = DocIdSetIterator.NO_MORE_DOCS;
|
||||
for (DisiWrapper scorer : allScorers) {
|
||||
if (scorer.doc < rangeEnd) {
|
||||
|
|
Loading…
Reference in New Issue