From 93d135e79d700572e2e384dff05f91579cea2ef9 Mon Sep 17 00:00:00 2001 From: jimczi Date: Wed, 2 Oct 2019 10:34:03 +0200 Subject: [PATCH] do not check global minimum score on non-competitive hits since it hurts constant score queries --- .../lucene/search/TopFieldCollector.java | 36 +++++++++++-------- .../lucene/search/TopScoreDocCollector.java | 35 ++++++++++-------- 2 files changed, 42 insertions(+), 29 deletions(-) diff --git a/lucene/core/src/java/org/apache/lucene/search/TopFieldCollector.java b/lucene/core/src/java/org/apache/lucene/search/TopFieldCollector.java index d4c05229ab2..7a8cb83f96e 100644 --- a/lucene/core/src/java/org/apache/lucene/search/TopFieldCollector.java +++ b/lucene/core/src/java/org/apache/lucene/search/TopFieldCollector.java @@ -126,7 +126,7 @@ public abstract class TopFieldCollector extends TopDocsCollector { super.setScorer(scorer); // reset the minimum competitive score minCompetitiveScore = 0f; - updateMinCompetitiveScore(scorer, true); + updateMinCompetitiveScore(scorer); } @Override @@ -145,8 +145,10 @@ public abstract class TopFieldCollector extends TopDocsCollector { } else { collectedAllCompetitiveHits = true; } - } else { - updateMinCompetitiveScore(scorer, totalHitsRelation == Relation.EQUAL_TO); + } else if (totalHitsRelation == TotalHits.Relation.EQUAL_TO) { + // we can start setting the min competitive score if we just + // reached totalHitsThreshold + updateMinCompetitiveScore(scorer); } return; } @@ -155,7 +157,7 @@ public abstract class TopFieldCollector extends TopDocsCollector { comparator.copy(bottom.slot, doc); updateBottom(doc); comparator.setBottom(bottom.slot); - updateMinCompetitiveScore(scorer, true); + updateMinCompetitiveScore(scorer); } else { // Startup transient: queue hasn't gathered numHits yet final int slot = totalHits - 1; @@ -166,7 +168,7 @@ public abstract class TopFieldCollector extends TopDocsCollector { if (queueFull) { comparator.setBottom(bottom.slot); } - updateMinCompetitiveScore(scorer, true); + updateMinCompetitiveScore(scorer); } } @@ -215,7 +217,7 @@ public abstract class TopFieldCollector extends TopDocsCollector { public void setScorer(Scorable scorer) throws IOException { super.setScorer(scorer); minCompetitiveScore = 0f; - updateMinCompetitiveScore(scorer, true); + updateMinCompetitiveScore(scorer); } @Override @@ -239,10 +241,10 @@ public abstract class TopFieldCollector extends TopDocsCollector { } else { collectedAllCompetitiveHits = true; } - } else { - // we just reached totalHitsThreshold, we can start setting the min - // competitive score now - updateMinCompetitiveScore(scorer, totalHitsRelation == Relation.EQUAL_TO); + } else if (totalHitsRelation == TotalHits.Relation.EQUAL_TO) { + // we can start setting the min competitive score if we just + // reached totalHitsThreshold + updateMinCompetitiveScore(scorer); } return; } @@ -251,7 +253,11 @@ public abstract class TopFieldCollector extends TopDocsCollector { final int topCmp = reverseMul * comparator.compareTop(doc); if (topCmp > 0 || (topCmp == 0 && doc <= afterDoc)) { // Already collected on a previous page - updateMinCompetitiveScore(scorer, totalHitsRelation == Relation.EQUAL_TO); + if (totalHitsRelation == TotalHits.Relation.EQUAL_TO) { + // we can start setting the min competitive score if we just + // reached totalHitsThreshold + updateMinCompetitiveScore(scorer); + } return; } @@ -262,7 +268,7 @@ public abstract class TopFieldCollector extends TopDocsCollector { updateBottom(doc); comparator.setBottom(bottom.slot); - updateMinCompetitiveScore(scorer, true); + updateMinCompetitiveScore(scorer); } else { collectedHits++; @@ -277,7 +283,7 @@ public abstract class TopFieldCollector extends TopDocsCollector { if (queueFull) { comparator.setBottom(bottom.slot); } - updateMinCompetitiveScore(scorer, true); + updateMinCompetitiveScore(scorer); } } }; @@ -336,10 +342,10 @@ public abstract class TopFieldCollector extends TopDocsCollector { return scoreMode; } - protected void updateMinCompetitiveScore(Scorable scorer, boolean checkQueue) throws IOException { + protected void updateMinCompetitiveScore(Scorable scorer) throws IOException { if (canSetMinScore && hitsThresholdChecker.isThresholdReached()) { boolean hasChanged = false; - if (checkQueue && queueFull) { + if (queueFull) { assert bottom != null && firstComparator != null; float localMinScore = firstComparator.value(bottom.slot); if (localMinScore > minCompetitiveScore) { diff --git a/lucene/core/src/java/org/apache/lucene/search/TopScoreDocCollector.java b/lucene/core/src/java/org/apache/lucene/search/TopScoreDocCollector.java index d7641a7a9d0..06d56fa8598 100644 --- a/lucene/core/src/java/org/apache/lucene/search/TopScoreDocCollector.java +++ b/lucene/core/src/java/org/apache/lucene/search/TopScoreDocCollector.java @@ -64,7 +64,7 @@ public abstract class TopScoreDocCollector extends TopDocsCollector { super.setScorer(scorer); // reset the minimum competitive score minCompetitiveScore = 0f; - updateMinCompetitiveScore(scorer, true); + updateMinCompetitiveScore(scorer); } @Override @@ -78,10 +78,11 @@ public abstract class TopScoreDocCollector extends TopDocsCollector { hitsThresholdChecker.incrementHitCount(); if (score <= pqTop.score) { - // the document is not competitive but we need to update the minimum competitive score - // if we just reached the total hits threshold or if the global minimum score (bottomValueChecker) - // has been updated - updateMinCompetitiveScore(scorer, totalHitsRelation == TotalHits.Relation.EQUAL_TO); + if (totalHitsRelation == TotalHits.Relation.EQUAL_TO) { + // we can start setting the min competitive score if we just + // reached totalHitsThreshold + updateMinCompetitiveScore(scorer); + } // Since docs are returned in-order (i.e., increasing doc Id), a document // with equal score to pqTop.score cannot compete since HitQueue favors // documents with lower doc Ids. Therefore reject those docs too. @@ -90,7 +91,7 @@ public abstract class TopScoreDocCollector extends TopDocsCollector { pqTop.doc = doc + docBase; pqTop.score = score; pqTop = pq.updateTop(); - updateMinCompetitiveScore(scorer, true); + updateMinCompetitiveScore(scorer); } }; @@ -140,25 +141,31 @@ public abstract class TopScoreDocCollector extends TopDocsCollector { if (score > after.score || (score == after.score && doc <= afterDoc)) { // hit was collected on a previous page - updateMinCompetitiveScore(scorer, totalHitsRelation == TotalHits.Relation.EQUAL_TO); + if (totalHitsRelation == TotalHits.Relation.EQUAL_TO) { + // we can start setting the min competitive score if we just + // reached totalHitsThreshold + updateMinCompetitiveScore(scorer); + } return; } if (score <= pqTop.score) { - // the document is not competitive but we need to update the minimum competitive score - // if we just reached the total hits threshold or if the global minimum score (bottomValueChecker) - // has been updated - updateMinCompetitiveScore(scorer, totalHitsRelation == TotalHits.Relation.EQUAL_TO); + if (totalHitsRelation == TotalHits.Relation.EQUAL_TO) { + // we can start setting the min competitive score if we just + // reached totalHitsThreshold + updateMinCompetitiveScore(scorer); + } // Since docs are returned in-order (i.e., increasing doc Id), a document // with equal score to pqTop.score cannot compete since HitQueue favors // documents with lower doc Ids. Therefore reject those docs too. + return; } collectedHits++; pqTop.doc = doc + docBase; pqTop.score = score; pqTop = pq.updateTop(); - updateMinCompetitiveScore(scorer, true); + updateMinCompetitiveScore(scorer); } }; } @@ -285,10 +292,10 @@ public abstract class TopScoreDocCollector extends TopDocsCollector { return pqTop != null && pqTop.score != Float.NEGATIVE_INFINITY; } - protected void updateMinCompetitiveScore(Scorable scorer, boolean checkQueue) throws IOException { + protected void updateMinCompetitiveScore(Scorable scorer) throws IOException { if (hitsThresholdChecker.isThresholdReached()) { boolean hasChanged = false; - if (checkQueue && isQueueFull()) { + if (isQueueFull()) { // since we tie-break on doc id and collect in doc id order, we can require // the next float float localMinScore = Math.nextUp(pqTop.score);