From 4d572cf207b73c726aabee7dbdede6f99058d131 Mon Sep 17 00:00:00 2001 From: Mayya Sharipova Date: Fri, 2 Oct 2020 11:50:42 -0400 Subject: [PATCH] LUCENE-9555 Ensure scorerIterator is fresh for opt Some collectors provide iterators that can efficiently skip non-competitive docs. When using DefaultBulkScorer#score function we create a conjunction of scorerIterator and collectorIterator. As collectorIterator always starts from a docID = -1, and for creation of conjunction iterator we need all of its sub-iterators to be on the same doc, the creation of conjuction iterator will fail if scorerIterator has already been advanced to some other document. This patch ensures that we create conjunction between scorerIterator and collectorIterator only if scorerIterator has not been advanced yet. Relates to #1725 Relates to #1937 --- lucene/CHANGES.txt | 3 +++ .../src/java/org/apache/lucene/search/Weight.java | 14 ++++++++++---- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/lucene/CHANGES.txt b/lucene/CHANGES.txt index dd2f012f2d8f..2952918dbf89 100644 --- a/lucene/CHANGES.txt +++ b/lucene/CHANGES.txt @@ -142,6 +142,9 @@ Improvements Bug fixes +* LUCENE-9555: For sort optimization, create conjunction between scorerIterator + and collectorIterator only if scorerIterator has not been advanced yet. (Mayya Sharipova) + * LUCENE-8663: NRTCachingDirectory.slowFileExists may open a file while it's inaccessible. (Dawid Weiss) diff --git a/lucene/core/src/java/org/apache/lucene/search/Weight.java b/lucene/core/src/java/org/apache/lucene/search/Weight.java index 9829836b7e24..746de53da3e0 100644 --- a/lucene/core/src/java/org/apache/lucene/search/Weight.java +++ b/lucene/core/src/java/org/apache/lucene/search/Weight.java @@ -203,10 +203,16 @@ public long cost() { public int score(LeafCollector collector, Bits acceptDocs, int min, int max) throws IOException { collector.setScorer(scorer); DocIdSetIterator scorerIterator = twoPhase == null ? iterator : twoPhase.approximation(); - DocIdSetIterator collectorIterator = collector.competitiveIterator(); - // if possible filter scorerIterator to keep only competitive docs as defined by collector - DocIdSetIterator filteredIterator = collectorIterator == null ? scorerIterator : - ConjunctionDISI.intersectIterators(Arrays.asList(scorerIterator, collectorIterator)); + + DocIdSetIterator filteredIterator = scorerIterator; + if (scorerIterator.docID() == -1) { + DocIdSetIterator collectorIterator = collector.competitiveIterator(); + if (collectorIterator != null) { + // filter scorerIterator to keep only competitive docs as defined by collector + filteredIterator = ConjunctionDISI.intersectIterators(Arrays.asList(scorerIterator, collectorIterator)); + } + } + if (filteredIterator.docID() == -1 && min == 0 && max == DocIdSetIterator.NO_MORE_DOCS) { scoreAll(collector, filteredIterator, twoPhase, acceptDocs); return DocIdSetIterator.NO_MORE_DOCS;