LUCENE-8732: ConstantScoreQuery can now early terminate the query if the minimum score is greater than the constant score and total hits are not requested

This commit is contained in:
jimczi 2019-03-27 18:09:23 +01:00
parent 1c46dd1f9b
commit 7e83451610
4 changed files with 52 additions and 20 deletions

View File

@ -82,6 +82,9 @@ Improvements
* LUCENE-8631: The Korean's user dictionary now picks the longest-matching word and discards
the other matches. (Yeongsu Kim via Jim Ferenczi)
* LUCENE-8732: ConstantScoreQuery can now early terminate the query if the minimum score is
greater than the constant score and total hits are not requested. (Jim Ferenczi)
Changes in Runtime Behavior
* LUCENE-8671: Load FST off-heap also for ID-like fields if reader is not opened

View File

@ -18,8 +18,6 @@ package org.apache.lucene.search;
import java.io.IOException;
import java.util.Collection;
import java.util.Collections;
import java.util.Objects;
import org.apache.lucene.index.IndexReader;
@ -115,9 +113,11 @@ public final class ConstantScoreQuery extends Query {
final Weight innerWeight = searcher.createWeight(query, ScoreMode.COMPLETE_NO_SCORES, 1f);
if (scoreMode.needsScores()) {
return new ConstantScoreWeight(this, boost) {
@Override
public BulkScorer bulkScorer(LeafReaderContext context) throws IOException {
if (scoreMode == ScoreMode.TOP_SCORES) {
return super.bulkScorer(context);
}
final BulkScorer innerScorer = innerWeight.bulkScorer(context);
if (innerScorer == null) {
return null;
@ -135,21 +135,12 @@ public final class ConstantScoreQuery extends Query {
@Override
public Scorer get(long leadCost) throws IOException {
final Scorer innerScorer = innerScorerSupplier.get(leadCost);
final float score = score();
return new FilterScorer(innerScorer) {
@Override
public float score() throws IOException {
return score;
}
@Override
public float getMaxScore(int upTo) throws IOException {
return score;
}
@Override
public Collection<ChildScorable> getChildren() {
return Collections.singleton(new ChildScorable(innerScorer, "constant"));
}
};
final TwoPhaseIterator twoPhaseIterator = innerScorer.twoPhaseIterator();
if (twoPhaseIterator == null) {
return new ConstantScoreScorer(innerWeight, score(), scoreMode, innerScorer.iterator());
} else {
return new ConstantScoreScorer(innerWeight, score(), scoreMode, twoPhaseIterator);
}
}
@Override

View File

@ -19,9 +19,13 @@ package org.apache.lucene.search;
import java.io.IOException;
import java.util.List;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.MockAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.LeafReaderContext;
import org.apache.lucene.index.RandomIndexWriter;
import org.apache.lucene.index.Term;
@ -216,4 +220,38 @@ public class TestConstantScoreScorer extends LuceneTestCase {
directory.close();
}
}
public void testEarlyTermination() throws IOException {
Analyzer analyzer = new MockAnalyzer(random());
Directory dir = newDirectory();
IndexWriter iw = new IndexWriter(dir, newIndexWriterConfig(analyzer).setMaxBufferedDocs(2).setMergePolicy(newLogMergePolicy()));
final int numDocs = 50;
for (int i = 0; i < numDocs; i++) {
Document doc = new Document();
Field f = newTextField("key", i % 2 == 0 ? "foo bar" : "baz", Field.Store.YES);
doc.add(f);
iw.addDocument(doc);
}
IndexReader ir = DirectoryReader.open(iw);
IndexSearcher is = newSearcher(ir);
TopScoreDocCollector c = TopScoreDocCollector.create(10, null, 10);
is.search(new ConstantScoreQuery(new TermQuery(new Term("key", "foo"))), c);
assertEquals(11, c.totalHits);
assertEquals(TotalHits.Relation.GREATER_THAN_OR_EQUAL_TO, c.totalHitsRelation);
c = TopScoreDocCollector.create(10, null, 10);
Query query = new BooleanQuery.Builder()
.add(new ConstantScoreQuery(new TermQuery(new Term("key", "foo"))), Occur.SHOULD)
.add(new ConstantScoreQuery(new TermQuery(new Term("key", "bar"))), Occur.FILTER)
.build();
is.search(query, c);
assertEquals(11, c.totalHits);
assertEquals(TotalHits.Relation.GREATER_THAN_OR_EQUAL_TO, c.totalHitsRelation);
iw.close();
ir.close();
dir.close();
}
}

View File

@ -496,7 +496,7 @@ public class TestRangeFacetCounts extends FacetTestCase {
} else {
ddq.add("field", range.getQuery(fastMatchQuery, vs));
}
assertEquals(expectedCounts[rangeID], s.search(ddq, 10).totalHits.value);
assertEquals(expectedCounts[rangeID], s.count(ddq));
}
}
@ -640,7 +640,7 @@ public class TestRangeFacetCounts extends FacetTestCase {
ddq.add("field", range.getQuery(fastMatchFilter, vs));
}
assertEquals(expectedCounts[rangeID], s.search(ddq, 10).totalHits.value);
assertEquals(expectedCounts[rangeID], s.count(ddq));
}
}