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) {