From 574245c96db19291138b2eb7253451b567c69d89 Mon Sep 17 00:00:00 2001 From: Mayya Sharipova Date: Tue, 6 Oct 2020 10:18:51 -0400 Subject: [PATCH] LUCENE-9565 Fix competitive iteration PR #1351 introduced a sort optimization where documents can be skipped. But iteration over competitive iterators was not properly organized, as they were not storing the current docID, and when competitive iterator was updated the current doc ID was lost. This patch fixed it. Relates to #1351 --- .../src/java/org/apache/lucene/search/Weight.java | 11 ++++++++--- .../lucene/search/comparators/DocComparator.java | 8 +++++--- .../lucene/search/comparators/NumericComparator.java | 8 +++++--- 3 files changed, 18 insertions(+), 9 deletions(-) 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 772093baad72..69954ba14eb5 100644 --- a/lucene/core/src/java/org/apache/lucene/search/Weight.java +++ b/lucene/core/src/java/org/apache/lucene/search/Weight.java @@ -204,9 +204,14 @@ public int score(LeafCollector collector, Bits acceptDocs, int min, int max) thr 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 (collectorIterator != null) { + if (scorerIterator.docID() != -1) { + collectorIterator.advance(scorerIterator.docID()); + } + // 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; diff --git a/lucene/core/src/java/org/apache/lucene/search/comparators/DocComparator.java b/lucene/core/src/java/org/apache/lucene/search/comparators/DocComparator.java index 8974ca69c401..c0b3e2efdbdf 100644 --- a/lucene/core/src/java/org/apache/lucene/search/comparators/DocComparator.java +++ b/lucene/core/src/java/org/apache/lucene/search/comparators/DocComparator.java @@ -133,14 +133,16 @@ public DocIdSetIterator competitiveIterator() { return null; } else { return new DocIdSetIterator() { + private int docID = -1; + @Override public int nextDoc() throws IOException { - return competitiveIterator.nextDoc(); + return advance(docID + 1); } @Override public int docID() { - return competitiveIterator.docID(); + return docID; } @Override @@ -150,7 +152,7 @@ public long cost() { @Override public int advance(int target) throws IOException { - return competitiveIterator.advance(target); + return docID = competitiveIterator.advance(target); } }; } diff --git a/lucene/core/src/java/org/apache/lucene/search/comparators/NumericComparator.java b/lucene/core/src/java/org/apache/lucene/search/comparators/NumericComparator.java index dc166f71a8a4..fa5f2679cd3a 100644 --- a/lucene/core/src/java/org/apache/lucene/search/comparators/NumericComparator.java +++ b/lucene/core/src/java/org/apache/lucene/search/comparators/NumericComparator.java @@ -220,14 +220,16 @@ public PointValues.Relation compare(byte[] minPackedValue, byte[] maxPackedValue public DocIdSetIterator competitiveIterator() { if (enableSkipping == false) return null; return new DocIdSetIterator() { + private int docID = -1; + @Override public int nextDoc() throws IOException { - return competitiveIterator.nextDoc(); + return advance(docID + 1); } @Override public int docID() { - return competitiveIterator.docID(); + return docID; } @Override @@ -237,7 +239,7 @@ public long cost() { @Override public int advance(int target) throws IOException { - return competitiveIterator.advance(target); + return docID = competitiveIterator.advance(target); } }; }