LuXugang commented on code in PR #687: URL: https://github.com/apache/lucene/pull/687#discussion_r978331854
########## lucene/sandbox/src/java/org/apache/lucene/sandbox/search/IndexSortSortedNumericDocValuesRangeQuery.java: ########## @@ -214,12 +221,172 @@ public int count(LeafReaderContext context) throws IOException { }; } + /** + * Returns the first document whose packed value is greater than or equal (if allowEqual is true) + * to the provided packed value or -1 if all packed values are smaller than the provided one, + */ + public final int nextDoc(PointValues values, byte[] packedValue, boolean allowEqual) + throws IOException { + assert values.getNumDimensions() == 1; + final int bytesPerDim = values.getBytesPerDimension(); + final ByteArrayComparator comparator = ArrayUtil.getUnsignedComparator(bytesPerDim); + final Predicate<byte[]> biggerThan = + testPackedValue -> { + int cmp = comparator.compare(testPackedValue, 0, packedValue, 0); + return cmp > 0 || (cmp == 0 && allowEqual); + }; + return nextDoc(values.getPointTree(), biggerThan); + } + + private int nextDoc(PointValues.PointTree pointTree, Predicate<byte[]> biggerThan) + throws IOException { + if (biggerThan.test(pointTree.getMaxPackedValue()) == false) { + // doc is before us + return -1; + } else if (pointTree.moveToChild()) { + // navigate down + do { + final int doc = nextDoc(pointTree, biggerThan); + if (doc != -1) { + return doc; + } + } while (pointTree.moveToSibling()); + pointTree.moveToParent(); + return -1; + } else { + // doc is in this leaf + final int[] doc = {-1}; + pointTree.visitDocValues( + new IntersectVisitor() { + @Override + public void visit(int docID) { + throw new AssertionError("Invalid call to visit(docID)"); + } + + @Override + public void visit(int docID, byte[] packedValue) { + if (doc[0] == -1 && biggerThan.test(packedValue)) { + doc[0] = docID; + } + } + + @Override + public Relation compare(byte[] minPackedValue, byte[] maxPackedValue) { + return Relation.CELL_CROSSES_QUERY; + } + }); + return doc[0]; + } + } + + private boolean matchNone(PointValues points, byte[] queryLowerPoint, byte[] queryUpperPoint) + throws IOException { + final ByteArrayComparator comparator = + ArrayUtil.getUnsignedComparator(points.getBytesPerDimension()); + for (int dim = 0; dim < points.getNumDimensions(); dim++) { + int offset = dim * points.getBytesPerDimension(); + if (comparator.compare(points.getMinPackedValue(), offset, queryUpperPoint, offset) > 0 + || comparator.compare(points.getMaxPackedValue(), offset, queryLowerPoint, offset) < 0) { + return true; + } + } + return false; + } + + private boolean matchAll(PointValues points, byte[] queryLowerPoint, byte[] queryUpperPoint) + throws IOException { + final ByteArrayComparator comparator = + ArrayUtil.getUnsignedComparator(points.getBytesPerDimension()); + for (int dim = 0; dim < points.getNumDimensions(); dim++) { + int offset = dim * points.getBytesPerDimension(); + if (comparator.compare(points.getMinPackedValue(), offset, queryUpperPoint, offset) > 0) { + return false; + } + if (comparator.compare(points.getMaxPackedValue(), offset, queryLowerPoint, offset) < 0) { + return false; + } + if (comparator.compare(points.getMinPackedValue(), offset, queryLowerPoint, offset) < 0 + || comparator.compare(points.getMaxPackedValue(), offset, queryUpperPoint, offset) > 0) { + return false; + } + } + return true; + } + + private BoundedDocIdSetIterator getDocIdSetIteratorOrNullFromBkd( + LeafReaderContext context, DocIdSetIterator delegate) throws IOException { + Sort indexSort = context.reader().getMetaData().getSort(); + if (indexSort != null + && indexSort.getSort().length > 0 + && indexSort.getSort()[0].getField().equals(field) + && indexSort.getSort()[0].getReverse() == false) { + PointValues points = context.reader().getPointValues(field); + if (points == null) { + return null; + } + + if (points.getNumDimensions() != 1) { + return null; + } + + if (points.getBytesPerDimension() != Long.BYTES + && points.getBytesPerDimension() != Integer.BYTES) { + return null; + } + + // Each doc that has points has exactly one point. + if (points.size() == points.getDocCount()) { + + byte[] queryLowerPoint; + byte[] queryUpperPoint; + if (points.getBytesPerDimension() == Integer.BYTES) { + queryLowerPoint = IntPoint.pack((int) lowerValue).bytes; + queryUpperPoint = IntPoint.pack((int) upperValue).bytes; + } else { + queryLowerPoint = LongPoint.pack(lowerValue).bytes; + queryUpperPoint = LongPoint.pack(upperValue).bytes; + } + if (lowerValue > upperValue || matchNone(points, queryLowerPoint, queryUpperPoint)) { + return new BoundedDocIdSetIterator(0, 0, null); + } + int minDocId, maxDocId; + if (matchAll(points, queryLowerPoint, queryUpperPoint)) { + minDocId = 0; + maxDocId = context.reader().maxDoc(); + } else { + // >=queryLowerPoint + minDocId = nextDoc(points, queryLowerPoint, true); + + if (minDocId == -1) { + return new BoundedDocIdSetIterator(0, 0, null); + } + // >queryUpperPoint, + maxDocId = nextDoc(points, queryUpperPoint, false); + if (maxDocId == -1) { + maxDocId = context.reader().maxDoc(); + } + } + + if ((points.getDocCount() == context.reader().maxDoc())) { + return new BoundedDocIdSetIterator(minDocId, maxDocId, null); + } else { + return new BoundedDocIdSetIterator(minDocId, maxDocId, delegate); Review Comment: I saw Test did not cover this branch, maybe `(points.getDocCount() == context.reader().maxDoc())` is always true, we do not need this branch? -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: issues-unsubscr...@lucene.apache.org For queries about this service, please contact Infrastructure at: us...@infra.apache.org --------------------------------------------------------------------- To unsubscribe, e-mail: issues-unsubscr...@lucene.apache.org For additional commands, e-mail: issues-h...@lucene.apache.org