diff --git a/lucene/core/src/java/org/apache/lucene/document/SortedNumericDocValuesRangeQuery.java b/lucene/core/src/java/org/apache/lucene/document/SortedNumericDocValuesRangeQuery.java index e72c0f810619..4b964739667a 100644 --- a/lucene/core/src/java/org/apache/lucene/document/SortedNumericDocValuesRangeQuery.java +++ b/lucene/core/src/java/org/apache/lucene/document/SortedNumericDocValuesRangeQuery.java @@ -129,21 +129,16 @@ public ScorerSupplier scorerSupplier(LeafReaderContext context) throws IOExcepti } int maxDoc = context.reader().maxDoc(); - DocValuesSkipper skipper = context.reader().getDocValuesSkipper(field); - if (skipper != null) { - if (skipper.minValue() > upperValue || skipper.maxValue() < lowerValue) { - return null; - } - if (skipper.docCount() == maxDoc - && skipper.minValue() >= lowerValue - && skipper.maxValue() <= upperValue) { - - return ConstantScoreScorerSupplier.matchAll(score(), scoreMode, maxDoc); - } + int count = docCount(context); + if (count == 0) { + return null; + } else if (count == 1) { + return ConstantScoreScorerSupplier.matchAll(score(), scoreMode, maxDoc); } SortedNumericDocValues values = DocValues.getSortedNumeric(context.reader(), field); final NumericDocValues singleton = DocValues.unwrapSingleton(values); + final DocValuesSkipper skipper = context.reader().getDocValuesSkipper(field); TwoPhaseIterator iterator; if (singleton != null) { if (skipper != null) { @@ -199,19 +194,30 @@ public float matchCost() { @Override public int count(LeafReaderContext context) throws IOException { - DocValuesSkipper skipper = context.reader().getDocValuesSkipper(field); - if (skipper == null) { - return -1; - } - if (skipper.minValue() > upperValue || skipper.maxValue() < lowerValue) { - return 0; - } - if (skipper.docCount() == context.reader().maxDoc() - && skipper.minValue() >= lowerValue - && skipper.maxValue() <= upperValue) { + int cnt = docCount(context); + return switch (cnt) { + case 1 -> context.reader().numDocs(); + default -> cnt; + }; + } - return context.reader().numDocs(); + /* Returning 1 instead of LeafReader#numDocs as it may run in O(maxDoc) + * which is unnecessary when docCount is invoked from ScorerSupplier + */ + private int docCount(LeafReaderContext context) throws IOException { + final DocValuesSkipper skipper = context.reader().getDocValuesSkipper(field); + if (skipper != null) { + if (skipper.minValue() > upperValue || skipper.maxValue() < lowerValue) { + return 0; + } + if (skipper.docCount() == context.reader().maxDoc() + && skipper.minValue() >= lowerValue + && skipper.maxValue() <= upperValue) { + + return 1; + } } + return -1; } };