LUCENE-8900: Simplify MultiSorter.

This commit is contained in:
Adrien Grand 2019-07-09 16:18:47 +02:00
parent cfac486afd
commit 17f2f96a5c
1 changed files with 30 additions and 131 deletions

View File

@ -25,11 +25,11 @@ import org.apache.lucene.search.Sort;
import org.apache.lucene.search.SortField; import org.apache.lucene.search.SortField;
import org.apache.lucene.util.Bits; import org.apache.lucene.util.Bits;
import org.apache.lucene.util.LongValues; import org.apache.lucene.util.LongValues;
import org.apache.lucene.util.NumericUtils;
import org.apache.lucene.util.PriorityQueue; import org.apache.lucene.util.PriorityQueue;
import org.apache.lucene.util.packed.PackedInts; import org.apache.lucene.util.packed.PackedInts;
import org.apache.lucene.util.packed.PackedLongValues; import org.apache.lucene.util.packed.PackedLongValues;
@SuppressWarnings({"unchecked","rawtypes"})
final class MultiSorter { final class MultiSorter {
/** Does a merge sort of the leaves of the incoming reader, returning {@link DocMap} to map each leaf's /** Does a merge sort of the leaves of the incoming reader, returning {@link DocMap} to map each leaf's
@ -53,9 +53,9 @@ final class MultiSorter {
@Override @Override
public boolean lessThan(LeafAndDocID a, LeafAndDocID b) { public boolean lessThan(LeafAndDocID a, LeafAndDocID b) {
for(int i=0;i<comparables.length;i++) { for(int i=0;i<comparables.length;i++) {
int cmp = reverseMuls[i] * a.values[i].compareTo(b.values[i]); int cmp = Long.compare(a.valuesAsComparableLongs[i], b.valuesAsComparableLongs[i]);
if (cmp != 0) { if (cmp != 0) {
return cmp < 0; return reverseMuls[i] * cmp < 0;
} }
} }
@ -74,8 +74,7 @@ final class MultiSorter {
CodecReader reader = readers.get(i); CodecReader reader = readers.get(i);
LeafAndDocID leaf = new LeafAndDocID(i, reader.getLiveDocs(), reader.maxDoc(), comparables.length); LeafAndDocID leaf = new LeafAndDocID(i, reader.getLiveDocs(), reader.maxDoc(), comparables.length);
for(int j=0;j<comparables.length;j++) { for(int j=0;j<comparables.length;j++) {
leaf.values[j] = comparables[j][i].getComparable(leaf.docID); leaf.valuesAsComparableLongs[j] = comparables[j][i].getAsComparableLong(leaf.docID);
assert leaf.values[j] != null;
} }
queue.add(leaf); queue.add(leaf);
builders[i] = PackedLongValues.monotonicBuilder(PackedInts.COMPACT); builders[i] = PackedLongValues.monotonicBuilder(PackedInts.COMPACT);
@ -99,8 +98,7 @@ final class MultiSorter {
top.docID++; top.docID++;
if (top.docID < top.maxDoc) { if (top.docID < top.maxDoc) {
for(int j=0;j<comparables.length;j++) { for(int j=0;j<comparables.length;j++) {
top.values[j] = comparables[j][top.readerIndex].getComparable(top.docID); top.valuesAsComparableLongs[j] = comparables[j][top.readerIndex].getAsComparableLong(top.docID);
assert top.values[j] != null;
} }
queue.updateTop(); queue.updateTop();
} else { } else {
@ -134,20 +132,21 @@ final class MultiSorter {
final int readerIndex; final int readerIndex;
final Bits liveDocs; final Bits liveDocs;
final int maxDoc; final int maxDoc;
final Comparable[] values; final long[] valuesAsComparableLongs;
int docID; int docID;
public LeafAndDocID(int readerIndex, Bits liveDocs, int maxDoc, int numComparables) { public LeafAndDocID(int readerIndex, Bits liveDocs, int maxDoc, int numComparables) {
this.readerIndex = readerIndex; this.readerIndex = readerIndex;
this.liveDocs = liveDocs; this.liveDocs = liveDocs;
this.maxDoc = maxDoc; this.maxDoc = maxDoc;
this.values = new Comparable[numComparables]; this.valuesAsComparableLongs = new long[numComparables];
} }
} }
/** Returns an object for this docID whose .compareTo represents the requested {@link SortField} sort order. */ /** Returns a long so that the natural ordering of long values matches the
* ordering of doc IDs for the given comparator. */
private interface ComparableProvider { private interface ComparableProvider {
Comparable getComparable(int docID) throws IOException; long getAsComparableLong(int docID) throws IOException;
} }
/** Returns {@code ComparableProvider}s for the provided readers to represent the requested {@link SortField} sort order. */ /** Returns {@code ComparableProvider}s for the provided readers to represent the requested {@link SortField} sort order. */
@ -178,26 +177,11 @@ final class MultiSorter {
final SortedDocValues readerValues = values[readerIndex]; final SortedDocValues readerValues = values[readerIndex];
final LongValues globalOrds = ordinalMap.getGlobalOrds(readerIndex); final LongValues globalOrds = ordinalMap.getGlobalOrds(readerIndex);
providers[readerIndex] = new ComparableProvider() { providers[readerIndex] = new ComparableProvider() {
// used only by assert:
int lastDocID = -1;
private boolean docsInOrder(int docID) {
if (docID < lastDocID) {
throw new AssertionError("docs must be sent in order, but lastDocID=" + lastDocID + " vs docID=" + docID);
}
lastDocID = docID;
return true;
}
@Override @Override
public Comparable getComparable(int docID) throws IOException { public long getAsComparableLong(int docID) throws IOException {
assert docsInOrder(docID); if (readerValues.advanceExact(docID)) {
int readerDocID = readerValues.docID();
if (readerDocID < docID) {
readerDocID = readerValues.advance(docID);
}
if (readerDocID == docID) {
// translate segment's ord to global ord space: // translate segment's ord to global ord space:
return Math.toIntExact(globalOrds.get(readerValues.ordValue())); return globalOrds.get(readerValues.ordValue());
} else { } else {
return missingOrd; return missingOrd;
} }
@ -208,10 +192,11 @@ final class MultiSorter {
break; break;
case LONG: case LONG:
case INT:
{ {
final Long missingValue; final long missingValue;
if (sortField.getMissingValue() != null) { if (sortField.getMissingValue() != null) {
missingValue = (Long) sortField.getMissingValue(); missingValue = ((Number) sortField.getMissingValue()).longValue();
} else { } else {
missingValue = 0L; missingValue = 0L;
} }
@ -220,24 +205,9 @@ final class MultiSorter {
final NumericDocValues values = Sorter.getOrWrapNumeric(readers.get(readerIndex), sortField); final NumericDocValues values = Sorter.getOrWrapNumeric(readers.get(readerIndex), sortField);
providers[readerIndex] = new ComparableProvider() { providers[readerIndex] = new ComparableProvider() {
// used only by assert:
int lastDocID = -1;
private boolean docsInOrder(int docID) {
if (docID < lastDocID) {
throw new AssertionError("docs must be sent in order, but lastDocID=" + lastDocID + " vs docID=" + docID);
}
lastDocID = docID;
return true;
}
@Override @Override
public Comparable getComparable(int docID) throws IOException { public long getAsComparableLong(int docID) throws IOException {
assert docsInOrder(docID); if (values.advanceExact(docID)) {
int readerDocID = values.docID();
if (readerDocID < docID) {
readerDocID = values.advance(docID);
}
if (readerDocID == docID) {
return values.longValue(); return values.longValue();
} else { } else {
return missingValue; return missingValue;
@ -248,50 +218,9 @@ final class MultiSorter {
} }
break; break;
case INT:
{
final Integer missingValue;
if (sortField.getMissingValue() != null) {
missingValue = (Integer) sortField.getMissingValue();
} else {
missingValue = 0;
}
for(int readerIndex=0;readerIndex<readers.size();readerIndex++) {
final NumericDocValues values = Sorter.getOrWrapNumeric(readers.get(readerIndex), sortField);
providers[readerIndex] = new ComparableProvider() {
// used only by assert:
int lastDocID = -1;
private boolean docsInOrder(int docID) {
if (docID < lastDocID) {
throw new AssertionError("docs must be sent in order, but lastDocID=" + lastDocID + " vs docID=" + docID);
}
lastDocID = docID;
return true;
}
@Override
public Comparable getComparable(int docID) throws IOException {
assert docsInOrder(docID);
int readerDocID = values.docID();
if (readerDocID < docID) {
readerDocID = values.advance(docID);
}
if (readerDocID == docID) {
return (int) values.longValue();
} else {
return missingValue;
}
}
};
}
}
break;
case DOUBLE: case DOUBLE:
{ {
final Double missingValue; final double missingValue;
if (sortField.getMissingValue() != null) { if (sortField.getMissingValue() != null) {
missingValue = (Double) sortField.getMissingValue(); missingValue = (Double) sortField.getMissingValue();
} else { } else {
@ -302,28 +231,13 @@ final class MultiSorter {
final NumericDocValues values = Sorter.getOrWrapNumeric(readers.get(readerIndex), sortField); final NumericDocValues values = Sorter.getOrWrapNumeric(readers.get(readerIndex), sortField);
providers[readerIndex] = new ComparableProvider() { providers[readerIndex] = new ComparableProvider() {
// used only by assert:
int lastDocID = -1;
private boolean docsInOrder(int docID) {
if (docID < lastDocID) {
throw new AssertionError("docs must be sent in order, but lastDocID=" + lastDocID + " vs docID=" + docID);
}
lastDocID = docID;
return true;
}
@Override @Override
public Comparable getComparable(int docID) throws IOException { public long getAsComparableLong(int docID) throws IOException {
assert docsInOrder(docID); double value = missingValue;
int readerDocID = values.docID(); if (values.advanceExact(docID)) {
if (readerDocID < docID) { value = Double.longBitsToDouble(values.longValue());
readerDocID = values.advance(docID);
}
if (readerDocID == docID) {
return Double.longBitsToDouble(values.longValue());
} else {
return missingValue;
} }
return NumericUtils.doubleToSortableLong(value);
} }
}; };
} }
@ -332,7 +246,7 @@ final class MultiSorter {
case FLOAT: case FLOAT:
{ {
final Float missingValue; final float missingValue;
if (sortField.getMissingValue() != null) { if (sortField.getMissingValue() != null) {
missingValue = (Float) sortField.getMissingValue(); missingValue = (Float) sortField.getMissingValue();
} else { } else {
@ -343,28 +257,13 @@ final class MultiSorter {
final NumericDocValues values = Sorter.getOrWrapNumeric(readers.get(readerIndex), sortField); final NumericDocValues values = Sorter.getOrWrapNumeric(readers.get(readerIndex), sortField);
providers[readerIndex] = new ComparableProvider() { providers[readerIndex] = new ComparableProvider() {
// used only by assert:
int lastDocID = -1;
private boolean docsInOrder(int docID) {
if (docID < lastDocID) {
throw new AssertionError("docs must be sent in order, but lastDocID=" + lastDocID + " vs docID=" + docID);
}
lastDocID = docID;
return true;
}
@Override @Override
public Comparable getComparable(int docID) throws IOException { public long getAsComparableLong(int docID) throws IOException {
assert docsInOrder(docID); float value = missingValue;
int readerDocID = values.docID(); if (values.advanceExact(docID)) {
if (readerDocID < docID) { value = Float.intBitsToFloat((int) values.longValue());
readerDocID = values.advance(docID);
}
if (readerDocID == docID) {
return Float.intBitsToFloat((int) values.longValue());
} else {
return missingValue;
} }
return NumericUtils.floatToSortableInt(value);
} }
}; };
} }