MultiCollector shouldn't report that scores are needed when they're not. (#12083)

When sub collectors don't agree on their `ScoreMode`, `MultiCollector`
currently returns `COMPLETE`. This makes sense when assuming that there is
likely one collector computing top hits (`TOP_SCORES`) and another one
computing facets (`COMPLETE_NO_SCORES`) so `COMPLETE` makes sense. However it
is also possible to have one collector computing top hits by field (`TOP_DOCS`)
and another one doing facets (`COMPLETE_NO_SCORES`), and `MultiCollector`
shouldn't report that scores are needed in that case.
This commit is contained in:
Adrien Grand 2023-01-13 14:44:17 +01:00 committed by GitHub
parent 90a5a71448
commit b5062a2858
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 24 additions and 1 deletions

View File

@ -108,7 +108,13 @@ public class MultiCollector implements Collector {
if (scoreMode == null) {
scoreMode = collector.scoreMode();
} else if (scoreMode != collector.scoreMode()) {
return ScoreMode.COMPLETE;
// If score modes disagree, we don't try to be smart and just use one of the COMPLETE score
// modes depending on whether scores are needed or not.
if (scoreMode.needsScores() || collector.scoreMode().needsScores()) {
scoreMode = ScoreMode.COMPLETE;
} else {
scoreMode = ScoreMode.COMPLETE_NO_SCORES;
}
}
}
return scoreMode;

View File

@ -594,6 +594,23 @@ public class TestMultiCollector extends LuceneTestCase {
dir.close();
}
public void testMergeScoreModes() {
for (ScoreMode sm1 : ScoreMode.values()) {
for (ScoreMode sm2 : ScoreMode.values()) {
Collector c1 = new TerminatingDummyCollector(0, sm1);
Collector c2 = new TerminatingDummyCollector(0, sm2);
Collector c = MultiCollector.wrap(c1, c2);
if (sm1 == sm2) {
assertEquals(sm1, c.scoreMode());
} else if (sm1.needsScores() || sm2.needsScores()) {
assertEquals(ScoreMode.COMPLETE, c.scoreMode());
} else {
assertEquals(ScoreMode.COMPLETE_NO_SCORES, c.scoreMode());
}
}
}
}
private static class TerminatingDummyCollector extends DummyCollector {
private final int terminateOnDoc;