diff --git a/lucene/CHANGES.txt b/lucene/CHANGES.txt
index d244e9b8668..2d1f47afedd 100644
--- a/lucene/CHANGES.txt
+++ b/lucene/CHANGES.txt
@@ -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
diff --git a/lucene/misc/src/java/org/apache/lucene/index/sorter/NumericDocValuesSorter.java b/lucene/misc/src/java/org/apache/lucene/index/sorter/NumericDocValuesSorter.java
index b53cc0cab74..983fc67ac7f 100644
--- a/lucene/misc/src/java/org/apache/lucene/index/sorter/NumericDocValuesSorter.java
+++ b/lucene/misc/src/java/org/apache/lucene/index/sorter/NumericDocValuesSorter.java
@@ -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") + ")";
}
}
diff --git a/lucene/misc/src/java/org/apache/lucene/index/sorter/Sorter.java b/lucene/misc/src/java/org/apache/lucene/index/sorter/Sorter.java
index a4d9870b49d..325b2dc3df0 100644
--- a/lucene/misc/src/java/org/apache/lucene/index/sorter/Sorter.java
+++ b/lucene/misc/src/java/org/apache/lucene/index/sorter/Sorter.java
@@ -81,11 +81,12 @@ public abstract class Sorter {
}
- /** Sorts documents in reverse order.
- * NOTE: 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. NOTE: 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 {
@@ -111,7 +112,7 @@ public abstract class Sorter {
return "ReverseDocs";
}
};
-
+
private static final class DocValueSorterTemplate extends SorterTemplate {
private final int[] docs;
@@ -231,4 +232,9 @@ public abstract class Sorter {
*/
public abstract String getID();
+ @Override
+ public String toString() {
+ return getID();
+ }
+
}
diff --git a/lucene/misc/src/test/org/apache/lucene/index/sorter/IndexSortingTest.java b/lucene/misc/src/test/org/apache/lucene/index/sorter/IndexSortingTest.java
index 3ee666a5e0e..fefe41bd025 100644
--- a/lucene/misc/src/test/org/apache/lucene/index/sorter/IndexSortingTest.java
+++ b/lucene/misc/src/test/org/apache/lucene/index/sorter/IndexSortingTest.java
@@ -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) {