You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by dn...@apache.org on 2021/09/15 14:47:28 UTC
[lucene-solr] branch branch_8_10 updated: LUCENE-10106: Sort
optimization wrongly skip first docs
This is an automated email from the ASF dual-hosted git repository.
dnhatn pushed a commit to branch branch_8_10
in repository https://gitbox.apache.org/repos/asf/lucene-solr.git
The following commit(s) were added to refs/heads/branch_8_10 by this push:
new 75a5061 LUCENE-10106: Sort optimization wrongly skip first docs
75a5061 is described below
commit 75a5061d3715cc5d93c4cbe4f1fa62bf035eea11
Author: Nhat Nguyen <nh...@elastic.co>
AuthorDate: Wed Sep 15 10:16:27 2021 -0400
LUCENE-10106: Sort optimization wrongly skip first docs
The first documents of subsequent segments are mistakenly skipped when
sort optimization is enabled. We should initialize maxDocVisited in
NumericComparator to -1 instead of 0.
---
.../search/comparators/NumericComparator.java | 2 +-
.../apache/lucene/search/TestSortOptimization.java | 86 ++++++++++++++++++++++
2 files changed, 87 insertions(+), 1 deletion(-)
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 9836bc0..8c04748 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
@@ -84,7 +84,7 @@ public abstract class NumericComparator<T extends Number> extends FieldComparato
private DocIdSetIterator competitiveIterator;
private long iteratorCost;
- private int maxDocVisited = 0;
+ private int maxDocVisited = -1;
private int updateCounter = 0;
public NumericLeafComparator(LeafReaderContext context) throws IOException {
diff --git a/lucene/core/src/test/org/apache/lucene/search/TestSortOptimization.java b/lucene/core/src/test/org/apache/lucene/search/TestSortOptimization.java
index a6df7af..785c727 100644
--- a/lucene/core/src/test/org/apache/lucene/search/TestSortOptimization.java
+++ b/lucene/core/src/test/org/apache/lucene/search/TestSortOptimization.java
@@ -36,6 +36,10 @@ import org.apache.lucene.store.Directory;
import org.apache.lucene.util.LuceneTestCase;
import java.io.IOException;
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Collectors;
+import java.util.stream.LongStream;
import static org.apache.lucene.search.SortField.FIELD_DOC;
import static org.apache.lucene.search.SortField.FIELD_SCORE;
@@ -616,4 +620,86 @@ public class TestSortOptimization extends LuceneTestCase {
dir.close();
}
+ public void testMaxDocVisited() throws IOException {
+ Directory dir = newDirectory();
+ IndexWriter writer = new IndexWriter(dir, new IndexWriterConfig());
+ int numDocs = atLeast(10000);
+ long offset = 100 + random().nextInt(100);
+ long smallestValue = 50 + random().nextInt(50);
+ boolean flushed = false;
+ for (int i = 0; i < numDocs; ++i) {
+ Document doc = new Document();
+ doc.add(new NumericDocValuesField("my_field", i + offset));
+ doc.add(new LongPoint("my_field", i + offset));
+ writer.addDocument(doc);
+ if (i >= 5000 && flushed == false) {
+ flushed = true;
+ writer.flush();
+ // Index the smallest value to the first slot of the second segment
+ doc = new Document();
+ doc.add(new NumericDocValuesField("my_field", smallestValue));
+ doc.add(new LongPoint("my_field", smallestValue));
+ writer.addDocument(doc);
+ }
+ }
+ IndexReader reader = DirectoryReader.open(writer);
+ writer.close();
+ IndexSearcher searcher = new IndexSearcher(reader);
+ SortField sortField = new SortField("my_field", SortField.Type.LONG);
+ sortField.setCanUsePoints();
+ TopFieldDocs topDocs =
+ searcher.search(new MatchAllDocsQuery(), 1 + random().nextInt(100), new Sort(sortField));
+ FieldDoc fieldDoc = (FieldDoc) topDocs.scoreDocs[0];
+ assertEquals(smallestValue, ((Long) fieldDoc.fields[0]).intValue());
+ reader.close();
+ dir.close();
+ }
+
+ public void testRandomLong() throws IOException {
+ Directory dir = newDirectory();
+ IndexWriter writer = new IndexWriter(dir, new IndexWriterConfig());
+ List<Long> seqNos = LongStream.range(0, atLeast(10_000)).boxed().collect(Collectors.toList());
+ Collections.shuffle(seqNos, random());
+ int pendingDocs = 0;
+ for (long seqNo : seqNos) {
+ Document doc = new Document();
+ doc.add(new NumericDocValuesField("seq_no", seqNo));
+ doc.add(new LongPoint("seq_no", seqNo));
+ writer.addDocument(doc);
+ pendingDocs++;
+ if (pendingDocs > 500 && random().nextInt(100) <= 5) {
+ pendingDocs = 0;
+ writer.flush();
+ }
+ }
+ writer.flush();
+ seqNos.sort(Long::compare);
+ IndexReader reader = DirectoryReader.open(writer);
+ writer.close();
+ IndexSearcher searcher = new IndexSearcher(reader);
+ SortField sortField = new SortField("seq_no", SortField.Type.LONG);
+ sortField.setCanUsePoints();
+ int visitedHits = 0;
+ ScoreDoc after = null;
+ while (visitedHits < seqNos.size()) {
+ int batch = 1 + random().nextInt(100);
+ Query query =
+ random().nextBoolean()
+ ? new MatchAllDocsQuery()
+ : LongPoint.newRangeQuery("seq_no", 0, Long.MAX_VALUE);
+ TopDocs topDocs = searcher.searchAfter(after, query, batch, new Sort(sortField));
+ int expectedHits = Math.min(seqNos.size() - visitedHits, batch);
+ assertEquals(expectedHits, topDocs.scoreDocs.length);
+ after = topDocs.scoreDocs[expectedHits - 1];
+ for (int i = 0; i < topDocs.scoreDocs.length; i++) {
+ FieldDoc fieldDoc = (FieldDoc) topDocs.scoreDocs[i];
+ long expectedSeqNo = seqNos.get(visitedHits);
+ assertEquals(expectedSeqNo, ((Long) fieldDoc.fields[0]).intValue());
+ visitedHits++;
+ }
+ }
+ reader.close();
+ dir.close();
+ }
+
}