LUCENE-4904: add descending sort order to NumericDocValuesSorter

git-svn-id: https://svn.apache.org/repos/asf/lucene/dev/trunk@1466420 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Shai Erera 2013-04-10 10:54:12 +00:00
parent ae84b6a178
commit a2524c00c2
4 changed files with 54 additions and 21 deletions

View File

@ -177,6 +177,8 @@ New Features
with SortingMergePolicy, which allows to early terminate queries on sorted
indexes, when the sort order matches the index order. (Adrien Grand, Shai Erera)
* LUCENE-4904: Added descending sort order to NumericDocValuesSorter. (Shai Erera)
Optimizations
* LUCENE-4839: SorterTemplate.merge can now be overridden in order to replace

View File

@ -24,37 +24,58 @@ import org.apache.lucene.index.NumericDocValues;
/**
* A {@link Sorter} which sorts documents according to their
* {@link NumericDocValues}.
* {@link NumericDocValues}. One can specify ascending or descending sort order.
*
* @lucene.experimental
*/
public class NumericDocValuesSorter extends Sorter {
private final String fieldName;
private final boolean ascending;
/** Constructor over the given field name, and ascending sort order. */
public NumericDocValuesSorter(final String fieldName) {
this(fieldName, true);
}
/**
* Constructor over the given field name, and whether sorting should be
* ascending ({@code true}) or descending ({@code false}).
*/
public NumericDocValuesSorter(final String fieldName, boolean ascending) {
this.fieldName = fieldName;
this.ascending = ascending;
}
@Override
public Sorter.DocMap sort(final AtomicReader reader) throws IOException {
final NumericDocValues ndv = reader.getNumericDocValues(fieldName);
final DocComparator comparator = new DocComparator() {
@Override
public int compare(int docID1, int docID2) {
final long v1 = ndv.get(docID1);
final long v2 = ndv.get(docID2);
return v1 < v2 ? -1 : v1 == v2 ? 0 : 1;
}
};
final DocComparator comparator;
if (ascending) {
comparator = new DocComparator() {
@Override
public int compare(int docID1, int docID2) {
final long v1 = ndv.get(docID1);
final long v2 = ndv.get(docID2);
return v1 < v2 ? -1 : v1 == v2 ? 0 : 1;
}
};
} else {
comparator = new DocComparator() {
@Override
public int compare(int docID1, int docID2) {
final long v1 = ndv.get(docID1);
final long v2 = ndv.get(docID2);
return v1 > v2 ? -1 : v1 == v2 ? 0 : 1;
}
};
}
return sort(reader.maxDoc(), comparator);
}
@Override
public String getID() {
return "DocValues(" + fieldName + ",asc)";
return "DocValues(" + fieldName + "," + (ascending ? "ascending" : "descending") + ")";
}
}

View File

@ -81,11 +81,12 @@ public abstract class Sorter {
}
/** Sorts documents in reverse order.
* <b>NOTE</b>: This {@link Sorter} is not idempotent. Sorting an
* {@link AtomicReader} once or twice will return two different
* {@link AtomicReader} views. This {@link Sorter} should not be used with
* {@link SortingMergePolicy}. */
/**
* Sorts documents in reverse order. <b>NOTE</b>: This {@link Sorter} is not
* idempotent. Sorting an {@link AtomicReader} once or twice will return two
* different {@link AtomicReader} views. This {@link Sorter} should not be
* used with {@link SortingMergePolicy}.
*/
public static final Sorter REVERSE_DOCS = new Sorter() {
@Override
public DocMap sort(final AtomicReader reader) throws IOException {
@ -231,4 +232,9 @@ public abstract class Sorter {
*/
public abstract String getID();
@Override
public String toString() {
return getID();
}
}

View File

@ -32,7 +32,7 @@ import org.junit.BeforeClass;
public class IndexSortingTest extends SorterTestBase {
private static final Sorter[] SORTERS = new Sorter[] {
new NumericDocValuesSorter(NUMERIC_DV_FIELD),
new NumericDocValuesSorter(NUMERIC_DV_FIELD, true),
Sorter.REVERSE_DOCS,
};
@ -52,6 +52,10 @@ public class IndexSortingTest extends SorterTestBase {
Collections.reverse(values);
} else {
Collections.sort(values);
if (sorter instanceof NumericDocValuesSorter && random().nextBoolean()) {
sorter = new NumericDocValuesSorter(NUMERIC_DV_FIELD, false); // descending
Collections.reverse(values);
}
}
sortedValues = values.toArray(new Integer[values.size()]);
if (VERBOSE) {