Fix indent from 4 to 2 spaces ()

Files in org.apache.lucene.search.comparators package
has a wrong indent of 4 spaces instead of 2.
This patch fixes only the indent from 4 to correct 2 spaces
This commit is contained in:
Mayya Sharipova 2020-12-10 14:55:26 -05:00 committed by GitHub
parent 04b9a98060
commit ab0b17ec8c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 665 additions and 661 deletions

View File

@ -29,157 +29,159 @@ import java.io.IOException;
* Comparator that sorts by asc _doc * Comparator that sorts by asc _doc
*/ */
public class DocComparator extends FieldComparator<Integer> { public class DocComparator extends FieldComparator<Integer> {
private final int[] docIDs; private final int[] docIDs;
private final boolean enableSkipping; // if skipping functionality should be enabled private final boolean enableSkipping; // if skipping functionality should be enabled
private int bottom; private int bottom;
private int topValue; private int topValue;
private boolean topValueSet; private boolean topValueSet;
private boolean bottomValueSet; private boolean bottomValueSet;
private boolean hitsThresholdReached; private boolean hitsThresholdReached;
/** Creates a new comparator based on document ids for {@code numHits} */ /**
public DocComparator(int numHits, boolean reverse, int sortPost) { * Creates a new comparator based on document ids for {@code numHits}
this.docIDs = new int[numHits]; */
// skipping functionality is enabled if we are sorting by _doc in asc order as a primary sort public DocComparator(int numHits, boolean reverse, int sortPost) {
this.enableSkipping = (reverse == false && sortPost == 0); this.docIDs = new int[numHits];
// skipping functionality is enabled if we are sorting by _doc in asc order as a primary sort
this.enableSkipping = (reverse == false && sortPost == 0);
}
@Override
public int compare(int slot1, int slot2) {
// No overflow risk because docIDs are non-negative
return docIDs[slot1] - docIDs[slot2];
}
@Override
public LeafFieldComparator getLeafComparator(LeafReaderContext context) {
// TODO: can we "map" our docIDs to the current
// reader? saves having to then subtract on every
// compare call
return new DocLeafComparator(context);
}
@Override
public void setTopValue(Integer value) {
topValue = value;
topValueSet = true;
}
@Override
public Integer value(int slot) {
return Integer.valueOf(docIDs[slot]);
}
/**
* DocLeafComparator with skipping functionality.
* When sort by _doc asc, after collecting top N matches and enough hits, the comparator
* can skip all the following documents.
* When sort by _doc asc and "top" document is set after which search should start,
* the comparator provides an iterator that can quickly skip to the desired "top" document.
*/
private class DocLeafComparator implements LeafFieldComparator {
private final int docBase;
private final int minDoc;
private final int maxDoc;
private DocIdSetIterator competitiveIterator; // iterator that starts from topValue
public DocLeafComparator(LeafReaderContext context) {
this.docBase = context.docBase;
if (enableSkipping) {
this.minDoc = topValue + 1;
this.maxDoc = context.reader().maxDoc();
this.competitiveIterator = DocIdSetIterator.all(maxDoc);
} else {
this.minDoc = -1;
this.maxDoc = -1;
this.competitiveIterator = null;
}
} }
@Override @Override
public int compare(int slot1, int slot2) { public void setBottom(int slot) {
// No overflow risk because docIDs are non-negative bottom = docIDs[slot];
return docIDs[slot1] - docIDs[slot2]; bottomValueSet = true;
} updateIterator();
@Override
public LeafFieldComparator getLeafComparator(LeafReaderContext context) {
// TODO: can we "map" our docIDs to the current
// reader? saves having to then subtract on every
// compare call
return new DocLeafComparator(context);
} }
@Override @Override
public void setTopValue(Integer value) { public int compareBottom(int doc) {
topValue = value; // No overflow risk because docIDs are non-negative
topValueSet = true; return bottom - (docBase + doc);
} }
@Override @Override
public Integer value(int slot) { public int compareTop(int doc) {
return Integer.valueOf(docIDs[slot]); int docValue = docBase + doc;
return Integer.compare(topValue, docValue);
} }
@Override
/** public void copy(int slot, int doc) throws IOException {
* DocLeafComparator with skipping functionality. docIDs[slot] = docBase + doc;
* When sort by _doc asc, after collecting top N matches and enough hits, the comparator
* can skip all the following documents.
* When sort by _doc asc and "top" document is set after which search should start,
* the comparator provides an iterator that can quickly skip to the desired "top" document.
*/
private class DocLeafComparator implements LeafFieldComparator {
private final int docBase;
private final int minDoc;
private final int maxDoc;
private DocIdSetIterator competitiveIterator; // iterator that starts from topValue
public DocLeafComparator(LeafReaderContext context) {
this.docBase = context.docBase;
if (enableSkipping) {
this.minDoc = topValue + 1;
this.maxDoc = context.reader().maxDoc();
this.competitiveIterator = DocIdSetIterator.all(maxDoc);
} else {
this.minDoc = -1;
this.maxDoc = -1;
this.competitiveIterator = null;
}
}
@Override
public void setBottom(int slot) {
bottom = docIDs[slot];
bottomValueSet = true;
updateIterator();
}
@Override
public int compareBottom(int doc) {
// No overflow risk because docIDs are non-negative
return bottom - (docBase + doc);
}
@Override
public int compareTop(int doc) {
int docValue = docBase + doc;
return Integer.compare(topValue, docValue);
}
@Override
public void copy(int slot, int doc) throws IOException {
docIDs[slot] = docBase + doc;
}
@Override
public void setScorer(Scorable scorer) throws IOException {
// update an iterator on a new segment
updateIterator();
}
@Override
public DocIdSetIterator competitiveIterator() {
if (enableSkipping == false) {
return null;
} else {
return new DocIdSetIterator() {
private int docID = -1;
@Override
public int nextDoc() throws IOException {
return advance(docID + 1);
}
@Override
public int docID() {
return docID;
}
@Override
public long cost() {
return competitiveIterator.cost();
}
@Override
public int advance(int target) throws IOException {
return docID = competitiveIterator.advance(target);
}
};
}
}
@Override
public void setHitsThresholdReached() {
hitsThresholdReached = true;
updateIterator();
}
private void updateIterator() {
if (enableSkipping == false || hitsThresholdReached == false) return;
if (bottomValueSet) {
// since we've collected top N matches, we can early terminate
// Currently early termination on _doc is also implemented in TopFieldCollector, but this will be removed
// once all bulk scores uses collectors' iterators
competitiveIterator = DocIdSetIterator.empty();
} else if (topValueSet) {
// skip to the desired top doc
if (docBase + maxDoc <= minDoc) {
competitiveIterator = DocIdSetIterator.empty(); // skip this segment
} else {
int segmentMinDoc = Math.max(competitiveIterator.docID(), minDoc - docBase);
competitiveIterator = new MinDocIterator(segmentMinDoc, maxDoc);
}
}
}
} }
@Override
public void setScorer(Scorable scorer) throws IOException {
// update an iterator on a new segment
updateIterator();
}
@Override
public DocIdSetIterator competitiveIterator() {
if (enableSkipping == false) {
return null;
} else {
return new DocIdSetIterator() {
private int docID = -1;
@Override
public int nextDoc() throws IOException {
return advance(docID + 1);
}
@Override
public int docID() {
return docID;
}
@Override
public long cost() {
return competitiveIterator.cost();
}
@Override
public int advance(int target) throws IOException {
return docID = competitiveIterator.advance(target);
}
};
}
}
@Override
public void setHitsThresholdReached() {
hitsThresholdReached = true;
updateIterator();
}
private void updateIterator() {
if (enableSkipping == false || hitsThresholdReached == false) return;
if (bottomValueSet) {
// since we've collected top N matches, we can early terminate
// Currently early termination on _doc is also implemented in TopFieldCollector, but this will be removed
// once all bulk scores uses collectors' iterators
competitiveIterator = DocIdSetIterator.empty();
} else if (topValueSet) {
// skip to the desired top doc
if (docBase + maxDoc <= minDoc) {
competitiveIterator = DocIdSetIterator.empty(); // skip this segment
} else {
int segmentMinDoc = Math.max(competitiveIterator.docID(), minDoc - docBase);
competitiveIterator = new MinDocIterator(segmentMinDoc, maxDoc);
}
}
}
}
} }

View File

@ -28,90 +28,90 @@ import java.io.IOException;
* This comparator provides a skipping functionality an iterator that can skip over non-competitive documents. * This comparator provides a skipping functionality an iterator that can skip over non-competitive documents.
*/ */
public class DoubleComparator extends NumericComparator<Double> { public class DoubleComparator extends NumericComparator<Double> {
private final double[] values; private final double[] values;
protected double topValue; protected double topValue;
protected double bottom; protected double bottom;
public DoubleComparator(int numHits, String field, Double missingValue, boolean reverse, int sortPos) { public DoubleComparator(int numHits, String field, Double missingValue, boolean reverse, int sortPos) {
super(field, missingValue != null ? missingValue : 0.0, reverse, sortPos, Double.BYTES); super(field, missingValue != null ? missingValue : 0.0, reverse, sortPos, Double.BYTES);
values = new double[numHits]; values = new double[numHits];
}
@Override
public int compare(int slot1, int slot2) {
return Double.compare(values[slot1], values[slot2]);
}
@Override
public void setTopValue(Double value) {
super.setTopValue(value);
topValue = value;
}
@Override
public Double value(int slot) {
return Double.valueOf(values[slot]);
}
@Override
public LeafFieldComparator getLeafComparator(LeafReaderContext context) throws IOException {
return new DoubleLeafComparator(context);
}
/**
* Leaf comparator for {@link DoubleComparator} that provides skipping functionality
*/
public class DoubleLeafComparator extends NumericLeafComparator {
public DoubleLeafComparator(LeafReaderContext context) throws IOException {
super(context);
}
private double getValueForDoc(int doc) throws IOException {
if (docValues.advanceExact(doc)) {
return Double.longBitsToDouble(docValues.longValue());
} else {
return missingValue;
}
} }
@Override @Override
public int compare(int slot1, int slot2) { public void setBottom(int slot) throws IOException {
return Double.compare(values[slot1], values[slot2]); bottom = values[slot];
super.setBottom(slot);
} }
@Override @Override
public void setTopValue(Double value) { public int compareBottom(int doc) throws IOException {
super.setTopValue(value); return Double.compare(bottom, getValueForDoc(doc));
topValue = value;
} }
@Override @Override
public Double value(int slot) { public int compareTop(int doc) throws IOException {
return Double.valueOf(values[slot]); return Double.compare(topValue, getValueForDoc(doc));
} }
@Override @Override
public LeafFieldComparator getLeafComparator(LeafReaderContext context) throws IOException { public void copy(int slot, int doc) throws IOException {
return new DoubleLeafComparator(context); values[slot] = getValueForDoc(doc);
super.copy(slot, doc);
} }
/** @Override
* Leaf comparator for {@link DoubleComparator} that provides skipping functionality protected boolean isMissingValueCompetitive() {
*/ int result = Double.compare(missingValue, bottom);
public class DoubleLeafComparator extends NumericLeafComparator { return reverse ? (result >= 0) : (result <= 0);
public DoubleLeafComparator(LeafReaderContext context) throws IOException {
super(context);
}
private double getValueForDoc(int doc) throws IOException {
if (docValues.advanceExact(doc)) {
return Double.longBitsToDouble(docValues.longValue());
} else {
return missingValue;
}
}
@Override
public void setBottom(int slot) throws IOException {
bottom = values[slot];
super.setBottom(slot);
}
@Override
public int compareBottom(int doc) throws IOException {
return Double.compare(bottom, getValueForDoc(doc));
}
@Override
public int compareTop(int doc) throws IOException {
return Double.compare(topValue, getValueForDoc(doc));
}
@Override
public void copy(int slot, int doc) throws IOException {
values[slot] = getValueForDoc(doc);
super.copy(slot, doc);
}
@Override
protected boolean isMissingValueCompetitive() {
int result = Double.compare(missingValue, bottom);
return reverse ? (result >= 0) : (result <= 0);
}
@Override
protected void encodeBottom(byte[] packedValue) {
DoublePoint.encodeDimension(bottom, packedValue, 0);
}
@Override
protected void encodeTop(byte[] packedValue) {
DoublePoint.encodeDimension(topValue, packedValue, 0);
}
} }
@Override
protected void encodeBottom(byte[] packedValue) {
DoublePoint.encodeDimension(bottom, packedValue, 0);
}
@Override
protected void encodeTop(byte[] packedValue) {
DoublePoint.encodeDimension(topValue, packedValue, 0);
}
}
} }

View File

@ -28,90 +28,90 @@ import java.io.IOException;
* This comparator provides a skipping functionality an iterator that can skip over non-competitive documents. * This comparator provides a skipping functionality an iterator that can skip over non-competitive documents.
*/ */
public class FloatComparator extends NumericComparator<Float> { public class FloatComparator extends NumericComparator<Float> {
private final float[] values; private final float[] values;
protected float topValue; protected float topValue;
protected float bottom; protected float bottom;
public FloatComparator(int numHits, String field, Float missingValue, boolean reverse, int sortPos) { public FloatComparator(int numHits, String field, Float missingValue, boolean reverse, int sortPos) {
super(field, missingValue != null ? missingValue : 0.0f, reverse, sortPos, Float.BYTES); super(field, missingValue != null ? missingValue : 0.0f, reverse, sortPos, Float.BYTES);
values = new float[numHits]; values = new float[numHits];
}
@Override
public int compare(int slot1, int slot2) {
return Float.compare(values[slot1], values[slot2]);
}
@Override
public void setTopValue(Float value) {
super.setTopValue(value);
topValue = value;
}
@Override
public Float value(int slot) {
return Float.valueOf(values[slot]);
}
@Override
public LeafFieldComparator getLeafComparator(LeafReaderContext context) throws IOException {
return new FloatLeafComparator(context);
}
/**
* Leaf comparator for {@link FloatComparator} that provides skipping functionality
*/
public class FloatLeafComparator extends NumericLeafComparator {
public FloatLeafComparator(LeafReaderContext context) throws IOException {
super(context);
}
private float getValueForDoc(int doc) throws IOException {
if (docValues.advanceExact(doc)) {
return Float.intBitsToFloat((int) docValues.longValue());
} else {
return missingValue;
}
} }
@Override @Override
public int compare(int slot1, int slot2) { public void setBottom(int slot) throws IOException {
return Float.compare(values[slot1], values[slot2]); bottom = values[slot];
super.setBottom(slot);
} }
@Override @Override
public void setTopValue(Float value) { public int compareBottom(int doc) throws IOException {
super.setTopValue(value); return Float.compare(bottom, getValueForDoc(doc));
topValue = value;
} }
@Override @Override
public Float value(int slot) { public int compareTop(int doc) throws IOException {
return Float.valueOf(values[slot]); return Float.compare(topValue, getValueForDoc(doc));
} }
@Override @Override
public LeafFieldComparator getLeafComparator(LeafReaderContext context) throws IOException { public void copy(int slot, int doc) throws IOException {
return new FloatLeafComparator(context); values[slot] = getValueForDoc(doc);
super.copy(slot, doc);
} }
/** @Override
* Leaf comparator for {@link FloatComparator} that provides skipping functionality protected boolean isMissingValueCompetitive() {
*/ int result = Float.compare(missingValue, bottom);
public class FloatLeafComparator extends NumericLeafComparator { return reverse ? (result >= 0) : (result <= 0);
public FloatLeafComparator(LeafReaderContext context) throws IOException {
super(context);
}
private float getValueForDoc(int doc) throws IOException {
if (docValues.advanceExact(doc)) {
return Float.intBitsToFloat((int) docValues.longValue());
} else {
return missingValue;
}
}
@Override
public void setBottom(int slot) throws IOException {
bottom = values[slot];
super.setBottom(slot);
}
@Override
public int compareBottom(int doc) throws IOException {
return Float.compare(bottom, getValueForDoc(doc));
}
@Override
public int compareTop(int doc) throws IOException {
return Float.compare(topValue, getValueForDoc(doc));
}
@Override
public void copy(int slot, int doc) throws IOException {
values[slot] = getValueForDoc(doc);
super.copy(slot, doc);
}
@Override
protected boolean isMissingValueCompetitive() {
int result = Float.compare(missingValue, bottom);
return reverse ? (result >= 0) : (result <= 0);
}
@Override
protected void encodeBottom(byte[] packedValue) {
FloatPoint.encodeDimension(bottom, packedValue, 0);
}
@Override
protected void encodeTop(byte[] packedValue) {
FloatPoint.encodeDimension(topValue, packedValue, 0);
}
} }
@Override
protected void encodeBottom(byte[] packedValue) {
FloatPoint.encodeDimension(bottom, packedValue, 0);
}
@Override
protected void encodeTop(byte[] packedValue) {
FloatPoint.encodeDimension(topValue, packedValue, 0);
}
}
} }

View File

@ -28,92 +28,92 @@ import java.io.IOException;
* This comparator provides a skipping functionality an iterator that can skip over non-competitive documents. * This comparator provides a skipping functionality an iterator that can skip over non-competitive documents.
*/ */
public class IntComparator extends NumericComparator<Integer> { public class IntComparator extends NumericComparator<Integer> {
private final int[] values; private final int[] values;
protected int topValue; protected int topValue;
protected int bottom; protected int bottom;
public IntComparator(int numHits, String field, Integer missingValue, boolean reverse, int sortPos) { public IntComparator(int numHits, String field, Integer missingValue, boolean reverse, int sortPos) {
super(field, missingValue != null ? missingValue : 0, reverse, sortPos, Integer.BYTES); super(field, missingValue != null ? missingValue : 0, reverse, sortPos, Integer.BYTES);
values = new int[numHits]; values = new int[numHits];
}
@Override
public int compare(int slot1, int slot2) {
return Integer.compare(values[slot1], values[slot2]);
}
@Override
public void setTopValue(Integer value) {
super.setTopValue(value);
topValue = value;
}
@Override
public Integer value(int slot) {
return Integer.valueOf(values[slot]);
}
@Override
public LeafFieldComparator getLeafComparator(LeafReaderContext context) throws IOException {
return new IntLeafComparator(context);
}
/**
* Leaf comparator for {@link IntComparator} that provides skipping functionality
*/
public class IntLeafComparator extends NumericLeafComparator {
public IntLeafComparator(LeafReaderContext context) throws IOException {
super(context);
}
private int getValueForDoc(int doc) throws IOException {
if (docValues.advanceExact(doc)) {
return (int) docValues.longValue();
} else {
return missingValue;
}
} }
@Override @Override
public int compare(int slot1, int slot2) { public void setBottom(int slot) throws IOException {
return Integer.compare(values[slot1], values[slot2]); bottom = values[slot];
super.setBottom(slot);
} }
@Override @Override
public void setTopValue(Integer value) { public int compareBottom(int doc) throws IOException {
super.setTopValue(value); return Integer.compare(bottom, getValueForDoc(doc));
topValue = value;
} }
@Override @Override
public Integer value(int slot) { public int compareTop(int doc) throws IOException {
return Integer.valueOf(values[slot]); return Integer.compare(topValue, getValueForDoc(doc));
} }
@Override @Override
public LeafFieldComparator getLeafComparator(LeafReaderContext context) throws IOException { public void copy(int slot, int doc) throws IOException {
return new IntLeafComparator(context); values[slot] = getValueForDoc(doc);
super.copy(slot, doc);
} }
/** @Override
* Leaf comparator for {@link IntComparator} that provides skipping functionality protected boolean isMissingValueCompetitive() {
*/ int result = Integer.compare(missingValue, bottom);
public class IntLeafComparator extends NumericLeafComparator { // in reverse (desc) sort missingValue is competitive when it's greater or equal to bottom,
// in asc sort missingValue is competitive when it's smaller or equal to bottom
public IntLeafComparator(LeafReaderContext context) throws IOException { return reverse ? (result >= 0) : (result <= 0);
super(context);
}
private int getValueForDoc(int doc) throws IOException {
if (docValues.advanceExact(doc)) {
return (int) docValues.longValue();
} else {
return missingValue;
}
}
@Override
public void setBottom(int slot) throws IOException {
bottom = values[slot];
super.setBottom(slot);
}
@Override
public int compareBottom(int doc) throws IOException {
return Integer.compare(bottom, getValueForDoc(doc));
}
@Override
public int compareTop(int doc) throws IOException {
return Integer.compare(topValue, getValueForDoc(doc));
}
@Override
public void copy(int slot, int doc) throws IOException {
values[slot] = getValueForDoc(doc);
super.copy(slot, doc);
}
@Override
protected boolean isMissingValueCompetitive() {
int result = Integer.compare(missingValue, bottom);
// in reverse (desc) sort missingValue is competitive when it's greater or equal to bottom,
// in asc sort missingValue is competitive when it's smaller or equal to bottom
return reverse ? (result >= 0) : (result <= 0);
}
@Override
protected void encodeBottom(byte[] packedValue) {
IntPoint.encodeDimension(bottom, packedValue, 0);
}
@Override
protected void encodeTop(byte[] packedValue) {
IntPoint.encodeDimension(topValue, packedValue, 0);
}
} }
@Override
protected void encodeBottom(byte[] packedValue) {
IntPoint.encodeDimension(bottom, packedValue, 0);
}
@Override
protected void encodeTop(byte[] packedValue) {
IntPoint.encodeDimension(topValue, packedValue, 0);
}
}
} }

View File

@ -28,92 +28,92 @@ import java.io.IOException;
* This comparator provides a skipping functionality an iterator that can skip over non-competitive documents. * This comparator provides a skipping functionality an iterator that can skip over non-competitive documents.
*/ */
public class LongComparator extends NumericComparator<Long> { public class LongComparator extends NumericComparator<Long> {
private final long[] values; private final long[] values;
protected long topValue; protected long topValue;
protected long bottom; protected long bottom;
public LongComparator(int numHits, String field, Long missingValue, boolean reverse, int sortPos) { public LongComparator(int numHits, String field, Long missingValue, boolean reverse, int sortPos) {
super(field,missingValue != null ? missingValue : 0L, reverse, sortPos, Long.BYTES); super(field, missingValue != null ? missingValue : 0L, reverse, sortPos, Long.BYTES);
values = new long[numHits]; values = new long[numHits];
}
@Override
public int compare(int slot1, int slot2) {
return Long.compare(values[slot1], values[slot2]);
}
@Override
public void setTopValue(Long value) {
super.setTopValue(value);
topValue = value;
}
@Override
public Long value(int slot) {
return Long.valueOf(values[slot]);
}
@Override
public LeafFieldComparator getLeafComparator(LeafReaderContext context) throws IOException {
return new LongLeafComparator(context);
}
/**
* Leaf comparator for {@link LongComparator} that provides skipping functionality
*/
public class LongLeafComparator extends NumericLeafComparator {
public LongLeafComparator(LeafReaderContext context) throws IOException {
super(context);
}
private long getValueForDoc(int doc) throws IOException {
if (docValues.advanceExact(doc)) {
return docValues.longValue();
} else {
return missingValue;
}
} }
@Override @Override
public int compare(int slot1, int slot2) { public void setBottom(int slot) throws IOException {
return Long.compare(values[slot1], values[slot2]); bottom = values[slot];
super.setBottom(slot);
} }
@Override @Override
public void setTopValue(Long value) { public int compareBottom(int doc) throws IOException {
super.setTopValue(value); return Long.compare(bottom, getValueForDoc(doc));
topValue = value;
} }
@Override @Override
public Long value(int slot) { public int compareTop(int doc) throws IOException {
return Long.valueOf(values[slot]); return Long.compare(topValue, getValueForDoc(doc));
} }
@Override @Override
public LeafFieldComparator getLeafComparator(LeafReaderContext context) throws IOException { public void copy(int slot, int doc) throws IOException {
return new LongLeafComparator(context); values[slot] = getValueForDoc(doc);
super.copy(slot, doc);
} }
/** @Override
* Leaf comparator for {@link LongComparator} that provides skipping functionality protected boolean isMissingValueCompetitive() {
*/ int result = Long.compare(missingValue, bottom);
public class LongLeafComparator extends NumericLeafComparator { // in reverse (desc) sort missingValue is competitive when it's greater or equal to bottom,
// in asc sort missingValue is competitive when it's smaller or equal to bottom
public LongLeafComparator(LeafReaderContext context) throws IOException { return reverse ? (result >= 0) : (result <= 0);
super(context);
}
private long getValueForDoc(int doc) throws IOException {
if (docValues.advanceExact(doc)) {
return docValues.longValue();
} else {
return missingValue;
}
}
@Override
public void setBottom(int slot) throws IOException {
bottom = values[slot];
super.setBottom(slot);
}
@Override
public int compareBottom(int doc) throws IOException {
return Long.compare(bottom, getValueForDoc(doc));
}
@Override
public int compareTop(int doc) throws IOException {
return Long.compare(topValue, getValueForDoc(doc));
}
@Override
public void copy(int slot, int doc) throws IOException {
values[slot] = getValueForDoc(doc);
super.copy(slot, doc);
}
@Override
protected boolean isMissingValueCompetitive() {
int result = Long.compare(missingValue, bottom);
// in reverse (desc) sort missingValue is competitive when it's greater or equal to bottom,
// in asc sort missingValue is competitive when it's smaller or equal to bottom
return reverse ? (result >= 0) : (result <= 0);
}
@Override
protected void encodeBottom(byte[] packedValue) {
LongPoint.encodeDimension(bottom, packedValue, 0);
}
@Override
protected void encodeTop(byte[] packedValue) {
LongPoint.encodeDimension(topValue, packedValue, 0);
}
} }
@Override
protected void encodeBottom(byte[] packedValue) {
LongPoint.encodeDimension(bottom, packedValue, 0);
}
@Override
protected void encodeTop(byte[] packedValue) {
LongPoint.encodeDimension(topValue, packedValue, 0);
}
}
} }

View File

@ -25,42 +25,42 @@ import java.io.IOException;
* Docs iterator that starts iterating from a configurable minimum document * Docs iterator that starts iterating from a configurable minimum document
*/ */
public class MinDocIterator extends DocIdSetIterator { public class MinDocIterator extends DocIdSetIterator {
final int segmentMinDoc; final int segmentMinDoc;
final int maxDoc; final int maxDoc;
int doc = -1; int doc = -1;
MinDocIterator(int segmentMinDoc, int maxDoc) { MinDocIterator(int segmentMinDoc, int maxDoc) {
this.segmentMinDoc = segmentMinDoc; this.segmentMinDoc = segmentMinDoc;
this.maxDoc = maxDoc; this.maxDoc = maxDoc;
} }
@Override @Override
public int docID() { public int docID() {
return doc; return doc;
} }
@Override @Override
public int nextDoc() throws IOException { public int nextDoc() throws IOException {
return advance(doc + 1); return advance(doc + 1);
} }
@Override @Override
public int advance(int target) throws IOException { public int advance(int target) throws IOException {
assert target > doc; assert target > doc;
if (doc == -1) { if (doc == -1) {
// skip directly to minDoc // skip directly to minDoc
doc = Math.max(target, segmentMinDoc); doc = Math.max(target, segmentMinDoc);
} else { } else {
doc = target; doc = target;
}
if (doc >= maxDoc) {
doc = NO_MORE_DOCS;
}
return doc;
} }
if (doc >= maxDoc) {
doc = NO_MORE_DOCS;
}
return doc;
}
@Override @Override
public long cost() { public long cost() {
return maxDoc - segmentMinDoc; return maxDoc - segmentMinDoc;
} }
} }

View File

@ -36,223 +36,225 @@ import java.util.Arrays;
* This comparator provides a skipping functionality an iterator that can skip over non-competitive documents. * This comparator provides a skipping functionality an iterator that can skip over non-competitive documents.
*/ */
public abstract class NumericComparator<T extends Number> extends FieldComparator<T> { public abstract class NumericComparator<T extends Number> extends FieldComparator<T> {
protected final T missingValue; protected final T missingValue;
protected final String field; protected final String field;
protected final boolean reverse; protected final boolean reverse;
private final int bytesCount; // how many bytes are used to encode this number private final int bytesCount; // how many bytes are used to encode this number
protected boolean topValueSet; protected boolean topValueSet;
protected boolean singleSort; // singleSort is true, if sort is based on a single sort field. protected boolean singleSort; // singleSort is true, if sort is based on a single sort field.
protected boolean hitsThresholdReached; protected boolean hitsThresholdReached;
protected boolean queueFull; protected boolean queueFull;
private boolean canSkipDocuments; private boolean canSkipDocuments;
protected NumericComparator(String field, T missingValue, boolean reverse, int sortPos, int bytesCount) { protected NumericComparator(String field, T missingValue, boolean reverse, int sortPos, int bytesCount) {
this.field = field; this.field = field;
this.missingValue = missingValue; this.missingValue = missingValue;
this.reverse = reverse; this.reverse = reverse;
this.canSkipDocuments = (sortPos == 0); // skipping functionality is only relevant for primary sort this.canSkipDocuments = (sortPos == 0); // skipping functionality is only relevant for primary sort
this.bytesCount = bytesCount; this.bytesCount = bytesCount;
} }
@Override @Override
public void setTopValue(T value) { public void setTopValue(T value) {
topValueSet = true; topValueSet = true;
} }
@Override @Override
public void setSingleSort() { public void setSingleSort() {
singleSort = true; singleSort = true;
} }
@Override @Override
public void disableSkipping() { public void disableSkipping() {
canSkipDocuments = false; canSkipDocuments = false;
}
/**
* Leaf comparator for {@link NumericComparator} that provides skipping functionality
*/
public abstract class NumericLeafComparator implements LeafFieldComparator {
protected final NumericDocValues docValues;
private final PointValues pointValues;
private final boolean enableSkipping; // if skipping functionality should be enabled on this segment
private final int maxDoc;
private final byte[] minValueAsBytes;
private final byte[] maxValueAsBytes;
private DocIdSetIterator competitiveIterator;
private long iteratorCost;
private int maxDocVisited = 0;
private int updateCounter = 0;
public NumericLeafComparator(LeafReaderContext context) throws IOException {
this.docValues = getNumericDocValues(context, field);
this.pointValues = canSkipDocuments ? context.reader().getPointValues(field) : null;
if (pointValues != null) {
this.enableSkipping = true; // skipping is enabled when points are available
this.maxDoc = context.reader().maxDoc();
this.maxValueAsBytes = reverse == false ? new byte[bytesCount] : topValueSet ? new byte[bytesCount] : null;
this.minValueAsBytes = reverse ? new byte[bytesCount] : topValueSet ? new byte[bytesCount] : null;
this.competitiveIterator = DocIdSetIterator.all(maxDoc);
this.iteratorCost = maxDoc;
} else {
this.enableSkipping = false;
this.maxDoc = 0;
this.maxValueAsBytes = null;
this.minValueAsBytes = null;
}
} }
/** /**
* Leaf comparator for {@link NumericComparator} that provides skipping functionality * Retrieves the NumericDocValues for the field in this segment
*/ */
public abstract class NumericLeafComparator implements LeafFieldComparator { protected NumericDocValues getNumericDocValues(LeafReaderContext context, String field) throws IOException {
protected final NumericDocValues docValues; return DocValues.getNumeric(context.reader(), field);
private final PointValues pointValues;
private final boolean enableSkipping; // if skipping functionality should be enabled on this segment
private final int maxDoc;
private final byte[] minValueAsBytes;
private final byte[] maxValueAsBytes;
private DocIdSetIterator competitiveIterator;
private long iteratorCost;
private int maxDocVisited = 0;
private int updateCounter = 0;
public NumericLeafComparator(LeafReaderContext context) throws IOException {
this.docValues = getNumericDocValues(context, field);
this.pointValues = canSkipDocuments ? context.reader().getPointValues(field) : null;
if (pointValues != null) {
this.enableSkipping = true; // skipping is enabled when points are available
this.maxDoc = context.reader().maxDoc();
this.maxValueAsBytes = reverse == false ? new byte[bytesCount] : topValueSet ? new byte[bytesCount] : null;
this.minValueAsBytes = reverse ? new byte[bytesCount] : topValueSet ? new byte[bytesCount] : null;
this.competitiveIterator = DocIdSetIterator.all(maxDoc);
this.iteratorCost = maxDoc;
} else {
this.enableSkipping = false;
this.maxDoc = 0;
this.maxValueAsBytes = null;
this.minValueAsBytes = null;
}
}
/** Retrieves the NumericDocValues for the field in this segment */
protected NumericDocValues getNumericDocValues(LeafReaderContext context, String field) throws IOException {
return DocValues.getNumeric(context.reader(), field);
}
@Override
public void setBottom(int slot) throws IOException {
queueFull = true; // if we are setting bottom, it means that we have collected enough hits
updateCompetitiveIterator(); // update an iterator if we set a new bottom
}
@Override
public void copy(int slot, int doc) throws IOException {
maxDocVisited = doc;
}
@Override
public void setScorer(Scorable scorer) throws IOException {
if (scorer instanceof Scorer) {
iteratorCost = ((Scorer) scorer).iterator().cost(); // starting iterator cost is the scorer's cost
updateCompetitiveIterator(); // update an iterator when we have a new segment
}
}
@Override
public void setHitsThresholdReached() throws IOException {
hitsThresholdReached = true;
updateCompetitiveIterator();
}
// update its iterator to include possibly only docs that are "stronger" than the current bottom entry
private void updateCompetitiveIterator() throws IOException {
if (enableSkipping == false || hitsThresholdReached == false || queueFull == false) return;
// if some documents have missing points, check that missing values prohibits optimization
if ((pointValues.getDocCount() < maxDoc) && isMissingValueCompetitive()) {
return; // we can't filter out documents, as documents with missing values are competitive
}
updateCounter++;
if (updateCounter > 256 && (updateCounter & 0x1f) != 0x1f) { // Start sampling if we get called too much
return;
}
if (reverse == false) {
encodeBottom(maxValueAsBytes);
if (topValueSet) {
encodeTop(minValueAsBytes);
}
} else {
encodeBottom(minValueAsBytes);
if (topValueSet) {
encodeTop(maxValueAsBytes);
}
}
DocIdSetBuilder result = new DocIdSetBuilder(maxDoc);
PointValues.IntersectVisitor visitor = new PointValues.IntersectVisitor() {
DocIdSetBuilder.BulkAdder adder;
@Override
public void grow(int count) {
adder = result.grow(count);
}
@Override
public void visit(int docID) {
if (docID <= maxDocVisited) {
return; // Already visited or skipped
}
adder.add(docID);
}
@Override
public void visit(int docID, byte[] packedValue) {
if (docID <= maxDocVisited) {
return; // already visited or skipped
}
if (maxValueAsBytes != null) {
int cmp = Arrays.compareUnsigned(packedValue, 0, bytesCount, maxValueAsBytes, 0, bytesCount);
// if doc's value is too high or for single sort even equal, it is not competitive and the doc can be skipped
if (cmp > 0 || (singleSort && cmp == 0)) return;
}
if (minValueAsBytes != null) {
int cmp = Arrays.compareUnsigned(packedValue, 0, bytesCount, minValueAsBytes, 0, bytesCount);
// if doc's value is too low or for single sort even equal, it is not competitive and the doc can be skipped
if (cmp < 0 || (singleSort && cmp == 0)) return;
}
adder.add(docID); // doc is competitive
}
@Override
public PointValues.Relation compare(byte[] minPackedValue, byte[] maxPackedValue) {
if (maxValueAsBytes != null) {
int cmp = Arrays.compareUnsigned(minPackedValue, 0, bytesCount, maxValueAsBytes, 0, bytesCount);
if (cmp > 0 || (singleSort && cmp == 0)) return PointValues.Relation.CELL_OUTSIDE_QUERY;
}
if (minValueAsBytes != null) {
int cmp = Arrays.compareUnsigned(maxPackedValue, 0, bytesCount, minValueAsBytes, 0, bytesCount);
if (cmp < 0 || (singleSort && cmp == 0)) return PointValues.Relation.CELL_OUTSIDE_QUERY;
}
if ((maxValueAsBytes != null && Arrays.compareUnsigned(maxPackedValue, 0, bytesCount, maxValueAsBytes, 0, bytesCount) > 0) ||
(minValueAsBytes != null && Arrays.compareUnsigned(minPackedValue, 0, bytesCount, minValueAsBytes, 0, bytesCount) < 0)) {
return PointValues.Relation.CELL_CROSSES_QUERY;
}
return PointValues.Relation.CELL_INSIDE_QUERY;
}
};
final long threshold = iteratorCost >>> 3;
long estimatedNumberOfMatches = pointValues.estimatePointCount(visitor); // runs in O(log(numPoints))
if (estimatedNumberOfMatches >= threshold) {
// the new range is not selective enough to be worth materializing, it doesn't reduce number of docs at least 8x
return;
}
pointValues.intersect(visitor);
competitiveIterator = result.build().iterator();
iteratorCost = competitiveIterator.cost();
}
@Override
public DocIdSetIterator competitiveIterator() {
if (enableSkipping == false) return null;
return new DocIdSetIterator() {
private int docID = -1;
@Override
public int nextDoc() throws IOException {
return advance(docID + 1);
}
@Override
public int docID() {
return docID;
}
@Override
public long cost() {
return competitiveIterator.cost();
}
@Override
public int advance(int target) throws IOException {
return docID = competitiveIterator.advance(target);
}
};
}
protected abstract boolean isMissingValueCompetitive();
protected abstract void encodeBottom(byte[] packedValue);
protected abstract void encodeTop(byte[] packedValue);
} }
@Override
public void setBottom(int slot) throws IOException {
queueFull = true; // if we are setting bottom, it means that we have collected enough hits
updateCompetitiveIterator(); // update an iterator if we set a new bottom
}
@Override
public void copy(int slot, int doc) throws IOException {
maxDocVisited = doc;
}
@Override
public void setScorer(Scorable scorer) throws IOException {
if (scorer instanceof Scorer) {
iteratorCost = ((Scorer) scorer).iterator().cost(); // starting iterator cost is the scorer's cost
updateCompetitiveIterator(); // update an iterator when we have a new segment
}
}
@Override
public void setHitsThresholdReached() throws IOException {
hitsThresholdReached = true;
updateCompetitiveIterator();
}
// update its iterator to include possibly only docs that are "stronger" than the current bottom entry
private void updateCompetitiveIterator() throws IOException {
if (enableSkipping == false || hitsThresholdReached == false || queueFull == false) return;
// if some documents have missing points, check that missing values prohibits optimization
if ((pointValues.getDocCount() < maxDoc) && isMissingValueCompetitive()) {
return; // we can't filter out documents, as documents with missing values are competitive
}
updateCounter++;
if (updateCounter > 256 && (updateCounter & 0x1f) != 0x1f) { // Start sampling if we get called too much
return;
}
if (reverse == false) {
encodeBottom(maxValueAsBytes);
if (topValueSet) {
encodeTop(minValueAsBytes);
}
} else {
encodeBottom(minValueAsBytes);
if (topValueSet) {
encodeTop(maxValueAsBytes);
}
}
DocIdSetBuilder result = new DocIdSetBuilder(maxDoc);
PointValues.IntersectVisitor visitor = new PointValues.IntersectVisitor() {
DocIdSetBuilder.BulkAdder adder;
@Override
public void grow(int count) {
adder = result.grow(count);
}
@Override
public void visit(int docID) {
if (docID <= maxDocVisited) {
return; // Already visited or skipped
}
adder.add(docID);
}
@Override
public void visit(int docID, byte[] packedValue) {
if (docID <= maxDocVisited) {
return; // already visited or skipped
}
if (maxValueAsBytes != null) {
int cmp = Arrays.compareUnsigned(packedValue, 0, bytesCount, maxValueAsBytes, 0, bytesCount);
// if doc's value is too high or for single sort even equal, it is not competitive and the doc can be skipped
if (cmp > 0 || (singleSort && cmp == 0)) return;
}
if (minValueAsBytes != null) {
int cmp = Arrays.compareUnsigned(packedValue, 0, bytesCount, minValueAsBytes, 0, bytesCount);
// if doc's value is too low or for single sort even equal, it is not competitive and the doc can be skipped
if (cmp < 0 || (singleSort && cmp == 0)) return;
}
adder.add(docID); // doc is competitive
}
@Override
public PointValues.Relation compare(byte[] minPackedValue, byte[] maxPackedValue) {
if (maxValueAsBytes != null) {
int cmp = Arrays.compareUnsigned(minPackedValue, 0, bytesCount, maxValueAsBytes, 0, bytesCount);
if (cmp > 0 || (singleSort && cmp == 0)) return PointValues.Relation.CELL_OUTSIDE_QUERY;
}
if (minValueAsBytes != null) {
int cmp = Arrays.compareUnsigned(maxPackedValue, 0, bytesCount, minValueAsBytes, 0, bytesCount);
if (cmp < 0 || (singleSort && cmp == 0)) return PointValues.Relation.CELL_OUTSIDE_QUERY;
}
if ((maxValueAsBytes != null && Arrays.compareUnsigned(maxPackedValue, 0, bytesCount, maxValueAsBytes, 0, bytesCount) > 0) ||
(minValueAsBytes != null && Arrays.compareUnsigned(minPackedValue, 0, bytesCount, minValueAsBytes, 0, bytesCount) < 0)) {
return PointValues.Relation.CELL_CROSSES_QUERY;
}
return PointValues.Relation.CELL_INSIDE_QUERY;
}
};
final long threshold = iteratorCost >>> 3;
long estimatedNumberOfMatches = pointValues.estimatePointCount(visitor); // runs in O(log(numPoints))
if (estimatedNumberOfMatches >= threshold) {
// the new range is not selective enough to be worth materializing, it doesn't reduce number of docs at least 8x
return;
}
pointValues.intersect(visitor);
competitiveIterator = result.build().iterator();
iteratorCost = competitiveIterator.cost();
}
@Override
public DocIdSetIterator competitiveIterator() {
if (enableSkipping == false) return null;
return new DocIdSetIterator() {
private int docID = -1;
@Override
public int nextDoc() throws IOException {
return advance(docID + 1);
}
@Override
public int docID() {
return docID;
}
@Override
public long cost() {
return competitiveIterator.cost();
}
@Override
public int advance(int target) throws IOException {
return docID = competitiveIterator.advance(target);
}
};
}
protected abstract boolean isMissingValueCompetitive();
protected abstract void encodeBottom(byte[] packedValue);
protected abstract void encodeTop(byte[] packedValue);
}
} }