mirror of https://github.com/apache/lucene.git
Fix indent from 4 to 2 spaces (#2129)
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:
parent
04b9a98060
commit
ab0b17ec8c
|
@ -29,157 +29,159 @@ import java.io.IOException;
|
|||
* Comparator that sorts by asc _doc
|
||||
*/
|
||||
public class DocComparator extends FieldComparator<Integer> {
|
||||
private final int[] docIDs;
|
||||
private final boolean enableSkipping; // if skipping functionality should be enabled
|
||||
private int bottom;
|
||||
private int topValue;
|
||||
private boolean topValueSet;
|
||||
private boolean bottomValueSet;
|
||||
private boolean hitsThresholdReached;
|
||||
private final int[] docIDs;
|
||||
private final boolean enableSkipping; // if skipping functionality should be enabled
|
||||
private int bottom;
|
||||
private int topValue;
|
||||
private boolean topValueSet;
|
||||
private boolean bottomValueSet;
|
||||
private boolean hitsThresholdReached;
|
||||
|
||||
/** Creates a new comparator based on document ids for {@code numHits} */
|
||||
public DocComparator(int numHits, boolean reverse, int sortPost) {
|
||||
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);
|
||||
/**
|
||||
* Creates a new comparator based on document ids for {@code numHits}
|
||||
*/
|
||||
public DocComparator(int numHits, boolean reverse, int sortPost) {
|
||||
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
|
||||
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);
|
||||
public void setBottom(int slot) {
|
||||
bottom = docIDs[slot];
|
||||
bottomValueSet = true;
|
||||
updateIterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTopValue(Integer value) {
|
||||
topValue = value;
|
||||
topValueSet = true;
|
||||
public int compareBottom(int doc) {
|
||||
// No overflow risk because docIDs are non-negative
|
||||
return bottom - (docBase + doc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer value(int slot) {
|
||||
return Integer.valueOf(docIDs[slot]);
|
||||
public int compareTop(int doc) {
|
||||
int docValue = docBase + doc;
|
||||
return Integer.compare(topValue, docValue);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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
|
||||
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 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,90 +28,90 @@ import java.io.IOException;
|
|||
* This comparator provides a skipping functionality – an iterator that can skip over non-competitive documents.
|
||||
*/
|
||||
public class DoubleComparator extends NumericComparator<Double> {
|
||||
private final double[] values;
|
||||
protected double topValue;
|
||||
protected double bottom;
|
||||
private final double[] values;
|
||||
protected double topValue;
|
||||
protected double bottom;
|
||||
|
||||
public DoubleComparator(int numHits, String field, Double missingValue, boolean reverse, int sortPos) {
|
||||
super(field, missingValue != null ? missingValue : 0.0, reverse, sortPos, Double.BYTES);
|
||||
values = new double[numHits];
|
||||
public DoubleComparator(int numHits, String field, Double missingValue, boolean reverse, int sortPos) {
|
||||
super(field, missingValue != null ? missingValue : 0.0, reverse, sortPos, Double.BYTES);
|
||||
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
|
||||
public int compare(int slot1, int slot2) {
|
||||
return Double.compare(values[slot1], values[slot2]);
|
||||
public void setBottom(int slot) throws IOException {
|
||||
bottom = values[slot];
|
||||
super.setBottom(slot);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTopValue(Double value) {
|
||||
super.setTopValue(value);
|
||||
topValue = value;
|
||||
public int compareBottom(int doc) throws IOException {
|
||||
return Double.compare(bottom, getValueForDoc(doc));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Double value(int slot) {
|
||||
return Double.valueOf(values[slot]);
|
||||
public int compareTop(int doc) throws IOException {
|
||||
return Double.compare(topValue, getValueForDoc(doc));
|
||||
}
|
||||
|
||||
@Override
|
||||
public LeafFieldComparator getLeafComparator(LeafReaderContext context) throws IOException {
|
||||
return new DoubleLeafComparator(context);
|
||||
public void copy(int slot, int doc) throws IOException {
|
||||
values[slot] = getValueForDoc(doc);
|
||||
super.copy(slot, doc);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
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 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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -28,90 +28,90 @@ import java.io.IOException;
|
|||
* This comparator provides a skipping functionality – an iterator that can skip over non-competitive documents.
|
||||
*/
|
||||
public class FloatComparator extends NumericComparator<Float> {
|
||||
private final float[] values;
|
||||
protected float topValue;
|
||||
protected float bottom;
|
||||
private final float[] values;
|
||||
protected float topValue;
|
||||
protected float bottom;
|
||||
|
||||
public FloatComparator(int numHits, String field, Float missingValue, boolean reverse, int sortPos) {
|
||||
super(field, missingValue != null ? missingValue : 0.0f, reverse, sortPos, Float.BYTES);
|
||||
values = new float[numHits];
|
||||
public FloatComparator(int numHits, String field, Float missingValue, boolean reverse, int sortPos) {
|
||||
super(field, missingValue != null ? missingValue : 0.0f, reverse, sortPos, Float.BYTES);
|
||||
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
|
||||
public int compare(int slot1, int slot2) {
|
||||
return Float.compare(values[slot1], values[slot2]);
|
||||
public void setBottom(int slot) throws IOException {
|
||||
bottom = values[slot];
|
||||
super.setBottom(slot);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTopValue(Float value) {
|
||||
super.setTopValue(value);
|
||||
topValue = value;
|
||||
public int compareBottom(int doc) throws IOException {
|
||||
return Float.compare(bottom, getValueForDoc(doc));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Float value(int slot) {
|
||||
return Float.valueOf(values[slot]);
|
||||
public int compareTop(int doc) throws IOException {
|
||||
return Float.compare(topValue, getValueForDoc(doc));
|
||||
}
|
||||
|
||||
@Override
|
||||
public LeafFieldComparator getLeafComparator(LeafReaderContext context) throws IOException {
|
||||
return new FloatLeafComparator(context);
|
||||
public void copy(int slot, int doc) throws IOException {
|
||||
values[slot] = getValueForDoc(doc);
|
||||
super.copy(slot, doc);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
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 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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -28,92 +28,92 @@ import java.io.IOException;
|
|||
* This comparator provides a skipping functionality – an iterator that can skip over non-competitive documents.
|
||||
*/
|
||||
public class IntComparator extends NumericComparator<Integer> {
|
||||
private final int[] values;
|
||||
protected int topValue;
|
||||
protected int bottom;
|
||||
private final int[] values;
|
||||
protected int topValue;
|
||||
protected int bottom;
|
||||
|
||||
public IntComparator(int numHits, String field, Integer missingValue, boolean reverse, int sortPos) {
|
||||
super(field, missingValue != null ? missingValue : 0, reverse, sortPos, Integer.BYTES);
|
||||
values = new int[numHits];
|
||||
public IntComparator(int numHits, String field, Integer missingValue, boolean reverse, int sortPos) {
|
||||
super(field, missingValue != null ? missingValue : 0, reverse, sortPos, Integer.BYTES);
|
||||
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
|
||||
public int compare(int slot1, int slot2) {
|
||||
return Integer.compare(values[slot1], values[slot2]);
|
||||
public void setBottom(int slot) throws IOException {
|
||||
bottom = values[slot];
|
||||
super.setBottom(slot);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTopValue(Integer value) {
|
||||
super.setTopValue(value);
|
||||
topValue = value;
|
||||
public int compareBottom(int doc) throws IOException {
|
||||
return Integer.compare(bottom, getValueForDoc(doc));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer value(int slot) {
|
||||
return Integer.valueOf(values[slot]);
|
||||
public int compareTop(int doc) throws IOException {
|
||||
return Integer.compare(topValue, getValueForDoc(doc));
|
||||
}
|
||||
|
||||
@Override
|
||||
public LeafFieldComparator getLeafComparator(LeafReaderContext context) throws IOException {
|
||||
return new IntLeafComparator(context);
|
||||
public void copy(int slot, int doc) throws IOException {
|
||||
values[slot] = getValueForDoc(doc);
|
||||
super.copy(slot, doc);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
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 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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -28,92 +28,92 @@ import java.io.IOException;
|
|||
* This comparator provides a skipping functionality – an iterator that can skip over non-competitive documents.
|
||||
*/
|
||||
public class LongComparator extends NumericComparator<Long> {
|
||||
private final long[] values;
|
||||
protected long topValue;
|
||||
protected long bottom;
|
||||
private final long[] values;
|
||||
protected long topValue;
|
||||
protected long bottom;
|
||||
|
||||
public LongComparator(int numHits, String field, Long missingValue, boolean reverse, int sortPos) {
|
||||
super(field,missingValue != null ? missingValue : 0L, reverse, sortPos, Long.BYTES);
|
||||
values = new long[numHits];
|
||||
public LongComparator(int numHits, String field, Long missingValue, boolean reverse, int sortPos) {
|
||||
super(field, missingValue != null ? missingValue : 0L, reverse, sortPos, Long.BYTES);
|
||||
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
|
||||
public int compare(int slot1, int slot2) {
|
||||
return Long.compare(values[slot1], values[slot2]);
|
||||
public void setBottom(int slot) throws IOException {
|
||||
bottom = values[slot];
|
||||
super.setBottom(slot);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTopValue(Long value) {
|
||||
super.setTopValue(value);
|
||||
topValue = value;
|
||||
public int compareBottom(int doc) throws IOException {
|
||||
return Long.compare(bottom, getValueForDoc(doc));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long value(int slot) {
|
||||
return Long.valueOf(values[slot]);
|
||||
public int compareTop(int doc) throws IOException {
|
||||
return Long.compare(topValue, getValueForDoc(doc));
|
||||
}
|
||||
|
||||
@Override
|
||||
public LeafFieldComparator getLeafComparator(LeafReaderContext context) throws IOException {
|
||||
return new LongLeafComparator(context);
|
||||
public void copy(int slot, int doc) throws IOException {
|
||||
values[slot] = getValueForDoc(doc);
|
||||
super.copy(slot, doc);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
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 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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -25,42 +25,42 @@ import java.io.IOException;
|
|||
* Docs iterator that starts iterating from a configurable minimum document
|
||||
*/
|
||||
public class MinDocIterator extends DocIdSetIterator {
|
||||
final int segmentMinDoc;
|
||||
final int maxDoc;
|
||||
int doc = -1;
|
||||
final int segmentMinDoc;
|
||||
final int maxDoc;
|
||||
int doc = -1;
|
||||
|
||||
MinDocIterator(int segmentMinDoc, int maxDoc) {
|
||||
this.segmentMinDoc = segmentMinDoc;
|
||||
this.maxDoc = maxDoc;
|
||||
}
|
||||
MinDocIterator(int segmentMinDoc, int maxDoc) {
|
||||
this.segmentMinDoc = segmentMinDoc;
|
||||
this.maxDoc = maxDoc;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int docID() {
|
||||
return doc;
|
||||
}
|
||||
@Override
|
||||
public int docID() {
|
||||
return doc;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int nextDoc() throws IOException {
|
||||
return advance(doc + 1);
|
||||
}
|
||||
@Override
|
||||
public int nextDoc() throws IOException {
|
||||
return advance(doc + 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int advance(int target) throws IOException {
|
||||
assert target > doc;
|
||||
if (doc == -1) {
|
||||
// skip directly to minDoc
|
||||
doc = Math.max(target, segmentMinDoc);
|
||||
} else {
|
||||
doc = target;
|
||||
}
|
||||
if (doc >= maxDoc) {
|
||||
doc = NO_MORE_DOCS;
|
||||
}
|
||||
return doc;
|
||||
@Override
|
||||
public int advance(int target) throws IOException {
|
||||
assert target > doc;
|
||||
if (doc == -1) {
|
||||
// skip directly to minDoc
|
||||
doc = Math.max(target, segmentMinDoc);
|
||||
} else {
|
||||
doc = target;
|
||||
}
|
||||
if (doc >= maxDoc) {
|
||||
doc = NO_MORE_DOCS;
|
||||
}
|
||||
return doc;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long cost() {
|
||||
return maxDoc - segmentMinDoc;
|
||||
}
|
||||
@Override
|
||||
public long cost() {
|
||||
return maxDoc - segmentMinDoc;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,223 +36,225 @@ import java.util.Arrays;
|
|||
* 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> {
|
||||
protected final T missingValue;
|
||||
protected final String field;
|
||||
protected final boolean reverse;
|
||||
private final int bytesCount; // how many bytes are used to encode this number
|
||||
protected final T missingValue;
|
||||
protected final String field;
|
||||
protected final boolean reverse;
|
||||
private final int bytesCount; // how many bytes are used to encode this number
|
||||
|
||||
protected boolean topValueSet;
|
||||
protected boolean singleSort; // singleSort is true, if sort is based on a single sort field.
|
||||
protected boolean hitsThresholdReached;
|
||||
protected boolean queueFull;
|
||||
private boolean canSkipDocuments;
|
||||
protected boolean topValueSet;
|
||||
protected boolean singleSort; // singleSort is true, if sort is based on a single sort field.
|
||||
protected boolean hitsThresholdReached;
|
||||
protected boolean queueFull;
|
||||
private boolean canSkipDocuments;
|
||||
|
||||
protected NumericComparator(String field, T missingValue, boolean reverse, int sortPos, int bytesCount) {
|
||||
this.field = field;
|
||||
this.missingValue = missingValue;
|
||||
this.reverse = reverse;
|
||||
this.canSkipDocuments = (sortPos == 0); // skipping functionality is only relevant for primary sort
|
||||
this.bytesCount = bytesCount;
|
||||
}
|
||||
protected NumericComparator(String field, T missingValue, boolean reverse, int sortPos, int bytesCount) {
|
||||
this.field = field;
|
||||
this.missingValue = missingValue;
|
||||
this.reverse = reverse;
|
||||
this.canSkipDocuments = (sortPos == 0); // skipping functionality is only relevant for primary sort
|
||||
this.bytesCount = bytesCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTopValue(T value) {
|
||||
topValueSet = true;
|
||||
}
|
||||
@Override
|
||||
public void setTopValue(T value) {
|
||||
topValueSet = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSingleSort() {
|
||||
singleSort = true;
|
||||
}
|
||||
@Override
|
||||
public void setSingleSort() {
|
||||
singleSort = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disableSkipping() {
|
||||
canSkipDocuments = false;
|
||||
@Override
|
||||
public void disableSkipping() {
|
||||
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 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;
|
||||
}
|
||||
}
|
||||
|
||||
/** 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);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue