排序函数获取
/** We cannot use the {@link FieldComparator} API because that API requires that you send it docIDs in order. Note that this API
* allocates arrays[maxDoc] to hold the native values needed for comparison, but 1) they are transient (only alive while sorting this one
* segment), and 2) in the typical index sorting case, they are only used to sort newly flushed segments, which will be smaller than
* merged segments. */
static DocComparator getDocComparator(int maxDoc,
SortField sortField,
SortedDocValuesSupplier sortedProvider,
NumericDocValuesSupplier numericProvider) throws IOException {
final int reverseMul = sortField.getReverse() ? -1 : 1;
final SortField.Type sortType = getSortFieldType(sortField);
switch(sortType) {
case STRING:
{
final SortedDocValues sorted = sortedProvider.get();
final int missingOrd;
if (sortField.getMissingValue() == SortField.STRING_LAST) {
missingOrd = Integer.MAX_VALUE;
} else {
missingOrd = Integer.MIN_VALUE;
}
final int[] ords = new int[maxDoc];
Arrays.fill(ords, missingOrd);
int docID;
while ((docID = sorted.nextDoc()) != NO_MORE_DOCS) {
ords[docID] = sorted.ordValue();
}
return new DocComparator() {
@Override
public int compare(int docID1, int docID2) {
return reverseMul * Integer.compare(ords[docID1], ords[docID2]);
}
};
}
case LONG:
{
final NumericDocValues dvs = numericProvider.get();
long[] values = new long[maxDoc];
if (sortField.getMissingValue() != null) {
Arrays.fill(values, (Long) sortField.getMissingValue());
}
while (true) {
int docID = dvs.nextDoc();
if (docID == NO_MORE_DOCS) {
break;
}
values[docID] = dvs.longValue();
}
return new DocComparator() {
@Override
public int compare(int docID1, int docID2) {
return reverseMul * Long.compare(values[docID1], values[docID2]);
}
};
}
case INT:
{
final NumericDocValues dvs = numericProvider.get();
int[] values = new int[maxDoc];
if (sortField.getMissingValue() != null) {
Arrays.fill(values, (Integer) sortField.getMissingValue());
}
while (true) {
int docID = dvs.nextDoc();
if (docID == NO_MORE_DOCS) {
break;
}
values[docID] = (int) dvs.longValue();
}
return new DocComparator() {
@Override
public int compare(int docID1, int docID2) {
return reverseMul * Integer.compare(values[docID1], values[docID2]);
}
};
}
case DOUBLE:
{
final NumericDocValues dvs = numericProvider.get();
double[] values = new double[maxDoc];
if (sortField.getMissingValue() != null) {
Arrays.fill(values, (Double) sortField.getMissingValue());
}
while (true) {
int docID = dvs.nextDoc();
if (docID == NO_MORE_DOCS) {
break;
}
values[docID] = Double.longBitsToDouble(dvs.longValue());
}
return new DocComparator() {
@Override
public int compare(int docID1, int docID2) {
return reverseMul * Double.compare(values[docID1], values[docID2]);
}
};
}
case FLOAT:
{
final NumericDocValues dvs = numericProvider.get();
float[] values = new float[maxDoc];
if (sortField.getMissingValue() != null) {
Arrays.fill(values, (Float) sortField.getMissingValue());
}
while (true) {
int docID = dvs.nextDoc();
if (docID == NO_MORE_DOCS) {
break;
}
values[docID] = Float.intBitsToFloat((int) dvs.longValue());
}
return new DocComparator() {
@Override
public int compare(int docID1, int docID2) {
return reverseMul * Float.compare(values[docID1], values[docID2]);
}
};
}
default:
throw new IllegalArgumentException("unhandled SortField.getType()=" + sortField.getType());
}
}
是否可以快速结束。 判断searchSort和indexSort是否是一致的。
org.apache.lucene.search.TopFieldCollector canEarlyTerminate
LeafMetaData 中包含了indexSort信息
this.metaData = new LeafMetaData(createdVersionMajor, si.info.getMinVersion(), si.info.getIndexSort());
static boolean canEarlyTerminate(Sort searchSort, Sort indexSort) {
final SortField[] fields1 = searchSort.getSort();
final SortField[] fields2 = indexSort.getSort();
// early termination is possible if fields1 is a prefix of fields2
if (fields1.length > fields2.length) {
return false;
}
return Arrays.asList(fields1).equals(Arrays.asList(fields2).subList(0, fields1.length));
}