mirror of https://github.com/apache/lucene.git
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:
parent
44e2e3155f
commit
328fdf9217
|
@ -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(); }
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -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(); }
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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}. */
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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());
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue