LUCENE-5493: merge Sorter and SortSorter (in progress)

git-svn-id: https://svn.apache.org/repos/asf/lucene/dev/branches/lucene5493@1574949 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Robert Muir 2014-03-06 16:28:12 +00:00
parent 44e2e3155f
commit 328fdf9217
6 changed files with 72 additions and 108 deletions

View File

@ -1,96 +0,0 @@
package org.apache.lucene.index.sorter;
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import java.io.IOException;
import org.apache.lucene.index.AtomicReader;
import org.apache.lucene.search.FieldComparator;
import org.apache.lucene.search.Scorer;
import org.apache.lucene.search.Sort;
import org.apache.lucene.search.SortField;
// nocommit: temporary class to engage the cutover!
class SortSorter extends Sorter {
final Sort sort;
public SortSorter(Sort sort) {
this.sort = sort;
}
@Override
public DocMap sort(AtomicReader reader) throws IOException {
SortField fields[] = sort.getSort();
final int reverseMul[] = new int[fields.length];
final FieldComparator<?> comparators[] = new FieldComparator[fields.length];
for (int i = 0; i < fields.length; i++) {
reverseMul[i] = fields[i].getReverse() ? -1 : 1;
comparators[i] = fields[i].getComparator(1, i);
comparators[i].setNextReader(reader.getContext());
comparators[i].setScorer(FAKESCORER);
}
final DocComparator comparator = new DocComparator() {
@Override
public int compare(int docID1, int docID2) {
try {
for (int i = 0; i < comparators.length; i++) {
// TODO: would be better if copy() didnt cause a term lookup in TermOrdVal & co,
// the segments are always the same here...
comparators[i].copy(0, docID1);
comparators[i].setBottom(0);
int comp = reverseMul[i] * comparators[i].compareBottom(docID2);
if (comp != 0) {
return comp;
}
}
return Integer.compare(docID1, docID2); // docid order tiebreak
} catch (IOException e) {
throw new RuntimeException(e);
}
}
};
return sort(reader.maxDoc(), comparator);
}
@Override
public String getID() {
return sort.toString();
}
static final Scorer FAKESCORER = new Scorer(null) {
@Override
public float score() throws IOException { throw new UnsupportedOperationException(); }
@Override
public int freq() throws IOException { throw new UnsupportedOperationException(); }
@Override
public int docID() { throw new UnsupportedOperationException(); }
@Override
public int nextDoc() throws IOException { throw new UnsupportedOperationException(); }
@Override
public int advance(int target) throws IOException { throw new UnsupportedOperationException(); }
@Override
public long cost() { throw new UnsupportedOperationException(); }
};
}

View File

@ -22,19 +22,25 @@ import java.util.Comparator;
import org.apache.lucene.index.AtomicReader; import org.apache.lucene.index.AtomicReader;
import org.apache.lucene.index.IndexReader; import org.apache.lucene.index.IndexReader;
import org.apache.lucene.search.FieldComparator;
import org.apache.lucene.search.Scorer;
import org.apache.lucene.search.Sort;
import org.apache.lucene.search.SortField;
import org.apache.lucene.util.TimSorter; import org.apache.lucene.util.TimSorter;
import org.apache.lucene.util.packed.MonotonicAppendingLongBuffer; import org.apache.lucene.util.packed.MonotonicAppendingLongBuffer;
/** /**
* Sorts documents of a given index by returning a permutation on the document * Sorts documents of a given index by returning a permutation on the document
* IDs. * IDs.
* <p><b>NOTE</b>: A {@link Sorter} implementation can be easily written from
* a {@link DocComparator document comparator} by using the
* {@link #sort(int, DocComparator)} helper method. This is especially useful
* when documents are directly comparable by their field values.
* @lucene.experimental * @lucene.experimental
*/ */
abstract class Sorter { final class Sorter {
final Sort sort;
/** Creates a new Sorter to sort the index with {@code sort} */
Sorter(Sort sort) {
this.sort = sort;
}
/** /**
* A permutation of doc IDs. For every document ID between <tt>0</tt> and * A permutation of doc IDs. For every document ID between <tt>0</tt> and
@ -54,7 +60,6 @@ abstract class Sorter {
* {@link AtomicReader#maxDoc() number of documents} of the * {@link AtomicReader#maxDoc() number of documents} of the
* {@link AtomicReader} which is sorted. */ * {@link AtomicReader} which is sorted. */
public abstract int size(); public abstract int size();
} }
/** Check consistency of a {@link DocMap}, useful for assertions. */ /** Check consistency of a {@link DocMap}, useful for assertions. */
@ -202,7 +207,39 @@ abstract class Sorter {
* <b>NOTE:</b> deleted documents are expected to appear in the mapping as * <b>NOTE:</b> deleted documents are expected to appear in the mapping as
* well, they will however be marked as deleted in the sorted view. * well, they will however be marked as deleted in the sorted view.
*/ */
public abstract DocMap sort(AtomicReader reader) throws IOException; public DocMap sort(AtomicReader reader) throws IOException {
SortField fields[] = sort.getSort();
final int reverseMul[] = new int[fields.length];
final FieldComparator<?> comparators[] = new FieldComparator[fields.length];
for (int i = 0; i < fields.length; i++) {
reverseMul[i] = fields[i].getReverse() ? -1 : 1;
comparators[i] = fields[i].getComparator(1, i);
comparators[i].setNextReader(reader.getContext());
comparators[i].setScorer(FAKESCORER);
}
final DocComparator comparator = new DocComparator() {
@Override
public int compare(int docID1, int docID2) {
try {
for (int i = 0; i < comparators.length; i++) {
// TODO: would be better if copy() didnt cause a term lookup in TermOrdVal & co,
// the segments are always the same here...
comparators[i].copy(0, docID1);
comparators[i].setBottom(0);
int comp = reverseMul[i] * comparators[i].compareBottom(docID2);
if (comp != 0) {
return comp;
}
}
return Integer.compare(docID1, docID2); // docid order tiebreak
} catch (IOException e) {
throw new RuntimeException(e);
}
}
};
return sort(reader.maxDoc(), comparator);
}
/** /**
* Returns the identifier of this {@link Sorter}. * Returns the identifier of this {@link Sorter}.
@ -211,11 +248,34 @@ abstract class Sorter {
* will have the same identifier. On the contrary, this identifier should be * will have the same identifier. On the contrary, this identifier should be
* different on different {@link Sorter sorters}. * different on different {@link Sorter sorters}.
*/ */
public abstract String getID(); public String getID() {
return sort.toString();
}
@Override @Override
public String toString() { public String toString() {
return getID(); return getID();
} }
static final Scorer FAKESCORER = new Scorer(null) {
@Override
public float score() throws IOException { throw new UnsupportedOperationException(); }
@Override
public int freq() throws IOException { throw new UnsupportedOperationException(); }
@Override
public int docID() { throw new UnsupportedOperationException(); }
@Override
public int nextDoc() throws IOException { throw new UnsupportedOperationException(); }
@Override
public int advance(int target) throws IOException { throw new UnsupportedOperationException(); }
@Override
public long cost() { throw new UnsupportedOperationException(); }
};
} }

View File

@ -712,7 +712,7 @@ public class SortingAtomicReader extends FilterAtomicReader {
* defined by <code>sorter</code>. If the reader is already sorted, this * defined by <code>sorter</code>. If the reader is already sorted, this
* method might return the reader as-is. */ * method might return the reader as-is. */
public static AtomicReader wrap(AtomicReader reader, Sort sort) throws IOException { public static AtomicReader wrap(AtomicReader reader, Sort sort) throws IOException {
return wrap(reader, new SortSorter(sort).sort(reader)); return wrap(reader, new Sorter(sort).sort(reader));
} }
/** Expert: same as {@link #wrap(AtomicReader, Sort)} but operates directly on a {@link Sorter.DocMap}. */ /** Expert: same as {@link #wrap(AtomicReader, Sort)} but operates directly on a {@link Sorter.DocMap}. */

View File

@ -179,7 +179,7 @@ public final class SortingMergePolicy extends MergePolicy {
/** Create a new {@link MergePolicy} that sorts documents with <code>sort</code>. */ /** Create a new {@link MergePolicy} that sorts documents with <code>sort</code>. */
public SortingMergePolicy(MergePolicy in, Sort sort) { public SortingMergePolicy(MergePolicy in, Sort sort) {
this.in = in; this.in = in;
this.sorter = new SortSorter(sort); this.sorter = new Sorter(sort);
this.sort = sort; this.sort = sort;
} }

View File

@ -33,7 +33,7 @@ public class SortingAtomicReaderTest extends SorterTestBase {
// sort the index by id (as integer, in NUMERIC_DV_FIELD) // sort the index by id (as integer, in NUMERIC_DV_FIELD)
Sort sort = new Sort(new SortField(NUMERIC_DV_FIELD, SortField.Type.INT)); Sort sort = new Sort(new SortField(NUMERIC_DV_FIELD, SortField.Type.INT));
final Sorter.DocMap docMap = new SortSorter(sort).sort(reader); final Sorter.DocMap docMap = new Sorter(sort).sort(reader);
// Sorter.compute also sorts the values // Sorter.compute also sorts the values
NumericDocValues dv = reader.getNumericDocValues(NUMERIC_DV_FIELD); NumericDocValues dv = reader.getNumericDocValues(NUMERIC_DV_FIELD);

View File

@ -98,7 +98,7 @@ public class TestBlockJoinSorter extends LuceneTestCase {
final Sort childSort = new Sort(new SortField("child_val", SortField.Type.LONG)); final Sort childSort = new Sort(new SortField("child_val", SortField.Type.LONG));
final Sort sort = new Sort(new SortField("custom", new BlockJoinComparatorSource(parentsFilter, parentSort, childSort))); final Sort sort = new Sort(new SortField("custom", new BlockJoinComparatorSource(parentsFilter, parentSort, childSort)));
final Sorter sorter = new SortSorter(sort); final Sorter sorter = new Sorter(sort);
final Sorter.DocMap docMap = sorter.sort(reader); final Sorter.DocMap docMap = sorter.sort(reader);
assertEquals(reader.maxDoc(), docMap.size()); assertEquals(reader.maxDoc(), docMap.size());