Index: src/test/org/apache/lucene/search/TestSort.java =================================================================== --- src/test/org/apache/lucene/search/TestSort.java (revision 800717) +++ src/test/org/apache/lucene/search/TestSort.java (working copy) @@ -412,7 +412,7 @@ bottomValue = slotValues[bottom]; } - public void setNextReader(IndexReader reader, int docBase, int numSlotsFull) throws IOException { + public void setNextReader(IndexReader reader, int docBase) throws IOException { docValues = FieldCache.DEFAULT.getInts(reader, "parser", new FieldCache.IntParser() { public final int parseInt(final String val) { return (val.charAt(0)-'A') * 123456; Index: src/test/org/apache/lucene/search/JustCompileSearch.java =================================================================== --- src/test/org/apache/lucene/search/JustCompileSearch.java (revision 800717) +++ src/test/org/apache/lucene/search/JustCompileSearch.java (working copy) @@ -221,7 +221,7 @@ throw new UnsupportedOperationException(UNSUPPORTED_MSG); } - public void setNextReader(IndexReader reader, int docBase, int numSlotsFull) + public void setNextReader(IndexReader reader, int docBase) throws IOException { throw new UnsupportedOperationException(UNSUPPORTED_MSG); } Index: src/test/org/apache/lucene/search/TestElevationComparator.java =================================================================== --- src/test/org/apache/lucene/search/TestElevationComparator.java (revision 800717) +++ src/test/org/apache/lucene/search/TestElevationComparator.java (working copy) @@ -21,7 +21,6 @@ import org.apache.lucene.document.Document; import org.apache.lucene.document.Field; import org.apache.lucene.index.*; -import org.apache.lucene.search.*; import org.apache.lucene.store.*; import org.apache.lucene.util.LuceneTestCase; @@ -165,7 +164,7 @@ values[slot] = docVal(doc); } - public void setNextReader(IndexReader reader, int docBase, int numSlotsFull) throws IOException { + public void setNextReader(IndexReader reader, int docBase) throws IOException { idIndex = FieldCache.DEFAULT.getStringIndex(reader, fieldname); } Index: src/java/org/apache/lucene/search/FieldValueHitQueue.java =================================================================== --- src/java/org/apache/lucene/search/FieldValueHitQueue.java (revision 800717) +++ src/java/org/apache/lucene/search/FieldValueHitQueue.java (working copy) @@ -76,7 +76,7 @@ SortField field = fields[0]; // AUTO is resolved before we are called assert field.getType() != SortField.AUTO; - comparator = field.getComparator(size, 0, field.reverse); + comparator = field.getComparator(size, 0); oneReverseMul = field.reverse ? -1 : 1; comparators[0] = comparator; @@ -127,7 +127,7 @@ assert field.getType() != SortField.AUTO; reverseMul[i] = field.reverse ? -1 : 1; - comparators[i] = field.getComparator(size, i, field.reverse); + comparators[i] = field.getComparator(size, i); } initialize(size); Index: src/java/org/apache/lucene/search/FieldComparator.java =================================================================== --- src/java/org/apache/lucene/search/FieldComparator.java (revision 800717) +++ src/java/org/apache/lucene/search/FieldComparator.java (working copy) @@ -31,12 +31,56 @@ import org.apache.lucene.search.FieldCache.StringIndex; /** - * A FieldComparator compares hits across multiple IndexReaders. + * Expert: a FieldComparator compares hits so as to determine their + * sort order when collecting the top results with {@link + * TopFieldCollector}. The concrete public FieldComparator + * classes here correspond to the SortField types. + * + *

This API is designed to achieve high performance + * sorting, by exposing a tight interaction with {@link + * FieldValueHitQueue} as it visits hits. Whenever a hit is + * competitive, it's enrolled into a virtual slot, which is + * an int ranging from 0 to numHits-1. The {@link + * FieldComparator} is made aware of segment transitions + * during searching in case any internal state it's tracking + * needs to be recomputed during these transitions.

+ * + *

A comparator must define these functions:

+ * + * * * NOTE: This API is experimental and might change in * incompatible ways in the next release. @@ -70,7 +114,7 @@ values[slot] = currentReaderValues[doc]; } - public void setNextReader(IndexReader reader, int docBase, int numSlotsFull) throws IOException { + public void setNextReader(IndexReader reader, int docBase) throws IOException { currentReaderValues = FieldCache.DEFAULT.getBytes(reader, field, parser); } @@ -111,7 +155,7 @@ docIDs[slot] = docBase + doc; } - public void setNextReader(IndexReader reader, int docBase, int numSlotsFull) { + public void setNextReader(IndexReader reader, int docBase) { // TODO: can we "map" our docIDs to the current // reader? saves having to then subtract on every // compare call @@ -173,7 +217,7 @@ values[slot] = currentReaderValues[doc]; } - public void setNextReader(IndexReader reader, int docBase, int numSlotsFull) throws IOException { + public void setNextReader(IndexReader reader, int docBase) throws IOException { currentReaderValues = FieldCache.DEFAULT.getDoubles(reader, field, parser); } @@ -236,7 +280,7 @@ values[slot] = currentReaderValues[doc]; } - public void setNextReader(IndexReader reader, int docBase, int numSlotsFull) throws IOException { + public void setNextReader(IndexReader reader, int docBase) throws IOException { currentReaderValues = FieldCache.DEFAULT.getFloats(reader, field, parser); } @@ -303,7 +347,7 @@ values[slot] = currentReaderValues[doc]; } - public void setNextReader(IndexReader reader, int docBase, int numSlotsFull) throws IOException { + public void setNextReader(IndexReader reader, int docBase) throws IOException { currentReaderValues = FieldCache.DEFAULT.getInts(reader, field, parser); } @@ -366,7 +410,7 @@ values[slot] = currentReaderValues[doc]; } - public void setNextReader(IndexReader reader, int docBase, int numSlotsFull) throws IOException { + public void setNextReader(IndexReader reader, int docBase) throws IOException { currentReaderValues = FieldCache.DEFAULT.getLongs(reader, field, parser); } @@ -413,7 +457,7 @@ scores[slot] = scorer.score(); } - public void setNextReader(IndexReader reader, int docBase, int numSlotsFull) { + public void setNextReader(IndexReader reader, int docBase) { } public void setBottom(final int bottom) { @@ -462,7 +506,7 @@ values[slot] = currentReaderValues[doc]; } - public void setNextReader(IndexReader reader, int docBase, int numSlotsFull) throws IOException { + public void setNextReader(IndexReader reader, int docBase) throws IOException { currentReaderValues = FieldCache.DEFAULT.getShorts(reader, field, parser); } @@ -526,7 +570,7 @@ values[slot] = currentReaderValues[doc]; } - public void setNextReader(IndexReader reader, int docBase, int numSlotsFull) throws IOException { + public void setNextReader(IndexReader reader, int docBase) throws IOException { currentReaderValues = FieldCache.DEFAULT.getStrings(reader, field); } @@ -543,9 +587,15 @@ } } - // NOTE: there were a number of other interesting String - // comparators explored, but this one seemed to perform - // best all around. See LUCENE-1483 for details. + /** Sorts by field's natural String sort order, using + * ordinals. This is functionally equivalent to {@link + * StringValComparator}, but it first resolves the string + * to their relative ordinal positions (using the index + * returned by {@link FieldCache#getStringIndex}), and + * does most comparisons using the ordinals. For medium + * to large results, this comparator will be much faster + * than {@link StringValComparator}. For very small + * result sets it may be slower. */ public static final class StringOrdValComparator extends FieldComparator { private final int[] ords; @@ -652,7 +702,7 @@ readerGen[slot] = currentReaderGen; } - public void setNextReader(IndexReader reader, int docBase, int numSlotsFull) throws IOException { + public void setNextReader(IndexReader reader, int docBase) throws IOException { StringIndex currentReaderValues = FieldCache.DEFAULT.getStringIndex(reader, field); currentReaderGen++; order = currentReaderValues.order; @@ -744,7 +794,7 @@ values[slot] = currentReaderValues[doc]; } - public void setNextReader(IndexReader reader, int docBase, int numSlotsFull) throws IOException { + public void setNextReader(IndexReader reader, int docBase) throws IOException { currentReaderValues = FieldCache.DEFAULT.getStrings(reader, field); } @@ -788,7 +838,7 @@ } /** - * Compare hit at slot1 with hit at slot2. Return + * Compare hit at slot1 with hit at slot2. * * @param slot1 first slot to compare * @param slot2 second slot to compare @@ -799,16 +849,25 @@ public abstract int compare(int slot1, int slot2); /** - * Set the bottom queue slot, ie the "weakest" (sorted - * last) entry in the queue. + * Set the bottom slot, ie the "weakest" (sorted last) + * entry in the queue. When {@link #compareBottom} is + * called, you should compare against this slot. This + * will always be called before {@link #compareBottom}. * - * @param slot the currently weakest (sorted lost) slot in the queue + * @param slot the currently weakest (sorted last) slot in the queue */ public abstract void setBottom(final int slot); /** * Compare the bottom of the queue with doc. This will - * only invoked after setBottom has been called. + * only invoked after setBottom has been called. This + * should return the same result as {@link + * #compare(int,int)}} as if bottom were slot1 and the new + * document were slot 2. + * + *

For a search that hits many results, this method + * will be the hotspot (invoked by far the most + * frequently).

* * @param doc that was hit * @return any N < 0 if the doc's value is sorted after @@ -819,7 +878,10 @@ public abstract int compareBottom(int doc) throws IOException; /** - * Copy hit (doc,score) to hit slot. + * This method is called when a new hit is competitive. + * You should copy any state associated with this document + * that will be required for future comparisons, into the + * specified slot. * * @param slot which slot to copy the hit to * @param doc docID relative to current reader @@ -834,22 +896,29 @@ * @throws IOException * @throws IOException */ - public abstract void setNextReader(IndexReader reader, int docBase, int numSlotsFull) throws IOException; + public abstract void setNextReader(IndexReader reader, int docBase) throws IOException; - /** Sets the Scorer to use in case a document's score is needed. */ + /** Sets the Scorer to use in case a document's score is + * needed. + * + * @param scorer Scorer instance that you should use to + * obtain the current hit's score, if necessary. */ public void setScorer(Scorer scorer) { // Empty implementation since most comparators don't need the score. This // can be overridden by those that need it. } /** + * Returns the SortField type corresponding to this + * comparator. + * * @return SortField.TYPE */ public abstract int sortType(); /** - * Return the actual value at slot. - * + * Return the actual value in the slot. + * * @param slot the value * @return value in this slot upgraded to Comparable */ Index: src/java/org/apache/lucene/search/SortField.java =================================================================== --- src/java/org/apache/lucene/search/SortField.java (revision 800717) +++ src/java/org/apache/lucene/search/SortField.java (working copy) @@ -443,16 +443,20 @@ } - /** Returns the {@link FieldComparator} to use for sorting. + /** Returns the {@link FieldComparator} to use for + * sorting. + * + * NOTE: This API is experimental and might change in + * incompatible ways in the next release. + * * @param numHits number of top hits the queue will store * @param sortPos position of this SortField within {@link * Sort}. The comparator is primary if sortPos==0, * secondary if sortPos==1, etc. Some comparators can * optimize themselves when they are the primary sort. - * @param reversed True if the SortField is reversed * @return {@link FieldComparator} to use when sorting */ - public FieldComparator getComparator(final int numHits, final int sortPos, final boolean reversed) throws IOException { + public FieldComparator getComparator(final int numHits, final int sortPos) throws IOException { if (locale != null) { // TODO: it'd be nice to allow FieldCache.getStringIndex @@ -488,10 +492,10 @@ case SortField.CUSTOM: assert factory == null && comparatorSource != null; - return comparatorSource.newComparator(field, numHits, sortPos, reversed); + return comparatorSource.newComparator(field, numHits, sortPos, reverse); case SortField.STRING: - return new FieldComparator.StringOrdValComparator(numHits, field, sortPos, reversed); + return new FieldComparator.StringOrdValComparator(numHits, field, sortPos, reverse); case SortField.STRING_VAL: return new FieldComparator.StringValComparator(numHits, field); Index: src/java/org/apache/lucene/search/TopFieldCollector.java =================================================================== --- src/java/org/apache/lucene/search/TopFieldCollector.java (revision 800717) +++ src/java/org/apache/lucene/search/TopFieldCollector.java (working copy) @@ -87,9 +87,8 @@ } public void setNextReader(IndexReader reader, int docBase) throws IOException { - final int numSlotsFull = queueFull ? numHits : totalHits; this.docBase = docBase; - comparator.setNextReader(reader, docBase, numSlotsFull); + comparator.setNextReader(reader, docBase); } public void setScorer(Scorer scorer) throws IOException { @@ -428,10 +427,9 @@ } public void setNextReader(IndexReader reader, int docBase) throws IOException { - final int numSlotsFull = queueFull ? numHits : totalHits; this.docBase = docBase; for (int i = 0; i < comparators.length; i++) { - comparators[i].setNextReader(reader, docBase, numSlotsFull); + comparators[i].setNextReader(reader, docBase); } } Index: contrib/remote/src/test/org/apache/lucene/search/TestRemoteSort.java =================================================================== --- contrib/remote/src/test/org/apache/lucene/search/TestRemoteSort.java (revision 800717) +++ contrib/remote/src/test/org/apache/lucene/search/TestRemoteSort.java (working copy) @@ -210,7 +210,7 @@ bottomValue = slotValues[bottom]; } - public void setNextReader(IndexReader reader, int docBase, int numSlotsFull) throws IOException { + public void setNextReader(IndexReader reader, int docBase) throws IOException { docValues = FieldCache.DEFAULT.getInts(reader, "parser", new FieldCache.IntParser() { public final int parseInt(final String val) { return (val.charAt(0)-'A') * 123456; Index: contrib/spatial/src/java/org/apache/lucene/spatial/tier/DistanceFieldComparatorSource.java =================================================================== --- contrib/spatial/src/java/org/apache/lucene/spatial/tier/DistanceFieldComparatorSource.java (revision 800717) +++ contrib/spatial/src/java/org/apache/lucene/spatial/tier/DistanceFieldComparatorSource.java (working copy) @@ -108,8 +108,8 @@ } @Override - public void setNextReader(IndexReader reader, int docBase, - int numSlotsFull) throws IOException { + public void setNextReader(IndexReader reader, int docBase) + throws IOException { // each reader in a segmented base // has an offset based on the maxDocs of previous readers