diff --git a/lucene/core/src/java/org/apache/lucene/search/PointInSetQuery.java b/lucene/core/src/java/org/apache/lucene/search/PointInSetQuery.java index 4da1c3efbc1..c00973ecb73 100644 --- a/lucene/core/src/java/org/apache/lucene/search/PointInSetQuery.java +++ b/lucene/core/src/java/org/apache/lucene/search/PointInSetQuery.java @@ -42,7 +42,6 @@ import org.apache.lucene.util.StringHelper; /** Finds all documents whose point value, previously indexed with e.g. {@link org.apache.lucene.document.LongPoint}, is contained in the * specified set */ -// nocommit explain that the 1D case must be pre-sorted public class PointInSetQuery extends Query { // A little bit overkill for us, since all of our "terms" are always in the same field: final PrefixCodedTerms sortedPackedPoints; @@ -51,7 +50,7 @@ public class PointInSetQuery extends Query { final int numDims; final int bytesPerDim; - /** {@code packedPoints} must already be sorted! */ + /** In the 1D case, the {@code packedPoints} iterator must be in sorted order. */ protected PointInSetQuery(String field, int numDims, int bytesPerDim, BytesRefIterator packedPoints) throws IOException { this.field = field; if (bytesPerDim < 1 || bytesPerDim > PointValues.MAX_NUM_BYTES) { @@ -61,6 +60,7 @@ public class PointInSetQuery extends Query { if (numDims < 1 || numDims > PointValues.MAX_DIMENSIONS) { throw new IllegalArgumentException("numDims must be > 0 and <= " + PointValues.MAX_DIMENSIONS + "; got " + numDims); } + this.numDims = numDims; // In the 1D case this works well (the more points, the more common prefixes they share, typically), but in @@ -74,9 +74,13 @@ public class PointInSetQuery extends Query { } if (previous == null) { previous = new BytesRefBuilder(); - // nocommit detect out-of-order 1D case - } else if (previous.get().equals(current)) { - continue; // deduplicate + } else { + int cmp = previous.get().compareTo(current); + if (cmp == 0) { + continue; // deduplicate + } else if (numDims == 1 && cmp > 0) { + throw new IllegalArgumentException("numDims=1 and values are out of order: saw " + previous + " before " + current); + } } builder.add(field, current); previous.copyBytes(current); diff --git a/lucene/core/src/test/org/apache/lucene/search/TestPointQueries.java b/lucene/core/src/test/org/apache/lucene/search/TestPointQueries.java index f9e63145784..51d914d0126 100644 --- a/lucene/core/src/test/org/apache/lucene/search/TestPointQueries.java +++ b/lucene/core/src/test/org/apache/lucene/search/TestPointQueries.java @@ -96,6 +96,33 @@ public class TestPointQueries extends LuceneTestCase { } } + public void testBasicInts() throws Exception { + Directory dir = newDirectory(); + IndexWriter w = new IndexWriter(dir, new IndexWriterConfig(new MockAnalyzer(random()))); + + Document doc = new Document(); + doc.add(new IntPoint("point", -7)); + w.addDocument(doc); + + doc = new Document(); + doc.add(new IntPoint("point", 0)); + w.addDocument(doc); + + doc = new Document(); + doc.add(new IntPoint("point", 3)); + w.addDocument(doc); + + DirectoryReader r = DirectoryReader.open(w); + IndexSearcher s = new IndexSearcher(r); + assertEquals(2, s.count(IntPoint.newRangeQuery("point", -8, false, 1, false))); + assertEquals(3, s.count(IntPoint.newRangeQuery("point", -7, true, 3, true))); + assertEquals(1, s.count(IntPoint.newExactQuery("point", -7))); + assertEquals(0, s.count(IntPoint.newExactQuery("point", -6))); + w.close(); + r.close(); + dir.close(); + } + public void testBasicFloats() throws Exception { Directory dir = newDirectory(); IndexWriter w = new IndexWriter(dir, new IndexWriterConfig(new MockAnalyzer(random()))); @@ -123,6 +150,33 @@ public class TestPointQueries extends LuceneTestCase { dir.close(); } + public void testBasicLongs() throws Exception { + Directory dir = newDirectory(); + IndexWriter w = new IndexWriter(dir, new IndexWriterConfig(new MockAnalyzer(random()))); + + Document doc = new Document(); + doc.add(new LongPoint("point", -7)); + w.addDocument(doc); + + doc = new Document(); + doc.add(new LongPoint("point", 0)); + w.addDocument(doc); + + doc = new Document(); + doc.add(new LongPoint("point", 3)); + w.addDocument(doc); + + DirectoryReader r = DirectoryReader.open(w); + IndexSearcher s = new IndexSearcher(r); + assertEquals(2, s.count(LongPoint.newRangeQuery("point", -8L, false, 1L, false))); + assertEquals(3, s.count(LongPoint.newRangeQuery("point", -7L, true, 3L, true))); + assertEquals(1, s.count(LongPoint.newExactQuery("point", -7L))); + assertEquals(0, s.count(LongPoint.newExactQuery("point", -6L))); + w.close(); + r.close(); + dir.close(); + } + public void testBasicDoubles() throws Exception { Directory dir = newDirectory(); IndexWriter w = new IndexWriter(dir, new IndexWriterConfig(new MockAnalyzer(random()))); @@ -1194,16 +1248,18 @@ public class TestPointQueries extends LuceneTestCase { boolean useNarrowRange = random().nextBoolean(); final Integer valueMin; final Integer valueMax; + int numValues; if (useNarrowRange) { int gap = random().nextInt(100); valueMin = random().nextInt(Integer.MAX_VALUE-gap); valueMax = valueMin + gap; + numValues = TestUtil.nextInt(random(), 1, gap+1); } else { valueMin = null; valueMax = null; + numValues = TestUtil.nextInt(random(), 1, 100); } final Set valuesSet = new HashSet<>(); - int numValues = TestUtil.nextInt(random(), 1, 100); while (valuesSet.size() < numValues) { valuesSet.add(randomIntValue(valueMin, valueMax)); } @@ -1285,7 +1341,7 @@ public class TestPointQueries extends LuceneTestCase { int numExtraValuesToQuery = random().nextInt(20); while (valuesToQuery.size() < numValidValuesToQuery + numExtraValuesToQuery) { - valuesToQuery.add(randomIntValue(valueMin, valueMax)); + valuesToQuery.add(random().nextInt()); } int expectedCount = 0;