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 with SortingMergePolicy, which allows to early terminate queries on sorted
indexes, when the sort order matches the index order. (Adrien Grand, Shai Erera) indexes, when the sort order matches the index order. (Adrien Grand, Shai Erera)
* LUCENE-4904: Added descending sort order to NumericDocValuesSorter. (Shai Erera)
Optimizations Optimizations
* LUCENE-4839: SorterTemplate.merge can now be overridden in order to replace * 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 * A {@link Sorter} which sorts documents according to their
* {@link NumericDocValues}. * {@link NumericDocValues}. One can specify ascending or descending sort order.
* *
* @lucene.experimental * @lucene.experimental
*/ */
public class NumericDocValuesSorter extends Sorter { public class NumericDocValuesSorter extends Sorter {
private final String fieldName; private final String fieldName;
private final boolean ascending;
/** Constructor over the given field name, and ascending sort order. */
public NumericDocValuesSorter(final String fieldName) { 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.fieldName = fieldName;
this.ascending = ascending;
} }
@Override @Override
public Sorter.DocMap sort(final AtomicReader reader) throws IOException { public Sorter.DocMap sort(final AtomicReader reader) throws IOException {
final NumericDocValues ndv = reader.getNumericDocValues(fieldName); final NumericDocValues ndv = reader.getNumericDocValues(fieldName);
final DocComparator comparator = new DocComparator() { final DocComparator comparator;
if (ascending) {
@Override comparator = new DocComparator() {
public int compare(int docID1, int docID2) { @Override
final long v1 = ndv.get(docID1); public int compare(int docID1, int docID2) {
final long v2 = ndv.get(docID2); final long v1 = ndv.get(docID1);
return v1 < v2 ? -1 : v1 == v2 ? 0 : 1; 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); return sort(reader.maxDoc(), comparator);
} }
@Override @Override
public String getID() { 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 * Sorts documents in reverse order. <b>NOTE</b>: This {@link Sorter} is not
* {@link AtomicReader} once or twice will return two different * idempotent. Sorting an {@link AtomicReader} once or twice will return two
* {@link AtomicReader} views. This {@link Sorter} should not be used with * different {@link AtomicReader} views. This {@link Sorter} should not be
* {@link SortingMergePolicy}. */ * used with {@link SortingMergePolicy}.
*/
public static final Sorter REVERSE_DOCS = new Sorter() { public static final Sorter REVERSE_DOCS = new Sorter() {
@Override @Override
public DocMap sort(final AtomicReader reader) throws IOException { public DocMap sort(final AtomicReader reader) throws IOException {
@ -111,7 +112,7 @@ public abstract class Sorter {
return "ReverseDocs"; return "ReverseDocs";
} }
}; };
private static final class DocValueSorterTemplate extends SorterTemplate { private static final class DocValueSorterTemplate extends SorterTemplate {
private final int[] docs; private final int[] docs;
@ -231,4 +232,9 @@ public abstract class Sorter {
*/ */
public abstract String getID(); 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 { public class IndexSortingTest extends SorterTestBase {
private static final Sorter[] SORTERS = new Sorter[] { private static final Sorter[] SORTERS = new Sorter[] {
new NumericDocValuesSorter(NUMERIC_DV_FIELD), new NumericDocValuesSorter(NUMERIC_DV_FIELD, true),
Sorter.REVERSE_DOCS, Sorter.REVERSE_DOCS,
}; };
@ -52,6 +52,10 @@ public class IndexSortingTest extends SorterTestBase {
Collections.reverse(values); Collections.reverse(values);
} else { } else {
Collections.sort(values); 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()]); sortedValues = values.toArray(new Integer[values.size()]);
if (VERBOSE) { if (VERBOSE) {