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
lucene/core/src/java/org/apache/lucene/search/comparators
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue