From 98caa4bc369dc0dd4f54fbae5f249c49203601d0 Mon Sep 17 00:00:00 2001 From: Costin Leau Date: Wed, 24 Jun 2026 08:51:44 +0300 Subject: [PATCH 1/2] Delegate rangeIntoBitSet in SingletonSortedNumericDocValues SingletonSortedNumericDocValues did not override rangeIntoBitSet, causing single-valued sorted numeric fields queried via SortedNumericDocValuesField.newSlowRangeQuery to fall back to per-doc scalar evaluation even when the underlying NumericDocValues has an optimized override. --- lucene/CHANGES.txt | 5 ++- .../SingletonSortedNumericDocValues.java | 7 ++++ .../TestSkipBlockRangeIteratorIntoBitSet.java | 39 +++++++++++++++++++ 3 files changed, 50 insertions(+), 1 deletion(-) diff --git a/lucene/CHANGES.txt b/lucene/CHANGES.txt index 42a6e8073576..c74a95b084a7 100644 --- a/lucene/CHANGES.txt +++ b/lucene/CHANGES.txt @@ -295,7 +295,10 @@ Optimizations Bug Fixes --------------------- -(No changes) + +* GITHUB#XXXXX: SingletonSortedNumericDocValues now delegates rangeIntoBitSet + to the wrapped NumericDocValues, enabling optimized range evaluation for + single-valued sorted numeric fields. (Costin Leau) Other --------------------- diff --git a/lucene/core/src/java/org/apache/lucene/index/SingletonSortedNumericDocValues.java b/lucene/core/src/java/org/apache/lucene/index/SingletonSortedNumericDocValues.java index 10783561819d..f2d3062ec5d0 100644 --- a/lucene/core/src/java/org/apache/lucene/index/SingletonSortedNumericDocValues.java +++ b/lucene/core/src/java/org/apache/lucene/index/SingletonSortedNumericDocValues.java @@ -73,6 +73,13 @@ public int docIDRunEnd() throws IOException { return in.docIDRunEnd(); } + @Override + public void rangeIntoBitSet( + int fromDoc, int toDoc, long minValue, long maxValue, FixedBitSet bitSet, int offset) + throws IOException { + in.rangeIntoBitSet(fromDoc, toDoc, minValue, maxValue, bitSet, offset); + } + @Override public long cost() { return in.cost(); diff --git a/lucene/core/src/test/org/apache/lucene/search/TestSkipBlockRangeIteratorIntoBitSet.java b/lucene/core/src/test/org/apache/lucene/search/TestSkipBlockRangeIteratorIntoBitSet.java index 76e01cae13c3..365757a65462 100644 --- a/lucene/core/src/test/org/apache/lucene/search/TestSkipBlockRangeIteratorIntoBitSet.java +++ b/lucene/core/src/test/org/apache/lucene/search/TestSkipBlockRangeIteratorIntoBitSet.java @@ -694,4 +694,43 @@ private void doTestSortedNumericRangeIntoBitSet(boolean dense, boolean fixedCard } } } + + public void testSingletonDelegatesRangeIntoBitSet() throws Exception { + int numDocs = 4096 * 4; + try (Directory dir = newDirectory()) { + IndexWriterConfig conf = new IndexWriterConfig(); + conf.setCodec(new Lucene104Codec()); + try (IndexWriter writer = new IndexWriter(dir, conf)) { + for (int i = 0; i < numDocs; i++) { + Document doc = new Document(); + long value = i % 100; + doc.add(NumericDocValuesField.indexedField("numeric", value)); + doc.add(SortedNumericDocValuesField.indexedField("sorted_numeric", value)); + writer.addDocument(doc); + } + writer.forceMerge(1); + } + try (DirectoryReader reader = DirectoryReader.open(dir)) { + for (LeafReaderContext ctx : reader.leaves()) { + int maxDoc = ctx.reader().maxDoc(); + + FixedBitSet fromNumeric = new FixedBitSet(maxDoc); + ctx.reader() + .getNumericDocValues("numeric") + .rangeIntoBitSet(0, maxDoc, 20, 40, fromNumeric, 0); + + FixedBitSet fromSingleton = new FixedBitSet(maxDoc); + ctx.reader() + .getSortedNumericDocValues("sorted_numeric") + .rangeIntoBitSet(0, maxDoc, 20, 40, fromSingleton, 0); + + assertEquals( + "Singleton sorted numeric should produce identical results to underlying numeric", + fromNumeric, + fromSingleton); + assertTrue("Expected some bits set", fromNumeric.cardinality() > 0); + } + } + } + } } From 8ffecb0e839d763d73082526a4758907650e295e Mon Sep 17 00:00:00 2001 From: Costin Leau Date: Thu, 25 Jun 2026 23:41:06 -0700 Subject: [PATCH 2/2] Update CHANGES.txt --- lucene/CHANGES.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lucene/CHANGES.txt b/lucene/CHANGES.txt index c74a95b084a7..9fd4552ec4ab 100644 --- a/lucene/CHANGES.txt +++ b/lucene/CHANGES.txt @@ -296,7 +296,7 @@ Optimizations Bug Fixes --------------------- -* GITHUB#XXXXX: SingletonSortedNumericDocValues now delegates rangeIntoBitSet +* GITHUB#16295: SingletonSortedNumericDocValues now delegates rangeIntoBitSet to the wrapped NumericDocValues, enabling optimized range evaluation for single-valued sorted numeric fields. (Costin Leau)