Index: lucene/src/java/org/apache/lucene/search/IndexSearcher.java --- lucene/src/java/org/apache/lucene/search/IndexSearcher.java Mon Feb 28 08:24:50 2011 -0500 +++ lucene/src/java/org/apache/lucene/search/IndexSearcher.java Mon Feb 28 11:11:18 2011 -0500 @@ -443,12 +443,20 @@ return search (leafContexts, weight, filter, nDocs, sort, fillFields); } else { // TODO: make this respect fillFields - final FieldDocSortedHitQueue hq = new FieldDocSortedHitQueue(nDocs); + //final FieldDocSortedHitQueue hq = new + //FieldDocSortedHitQueue(nDocs); + + final TopFieldCollector topCollector = TopFieldCollector.create(sort, nDocs, + fillFields, + fieldSortDoTrackScores, + fieldSortDoMaxScore, + false); + final Lock lock = new ReentrantLock(); final ExecutionHelper runner = new ExecutionHelper(executor); for (int i = 0; i < leafSlices.length; i++) { // search each leaf slice runner.submit( - new SearcherCallableWithSort(lock, this, leafSlices[i], weight, filter, nDocs, hq, sort)); + new SearcherCallableWithSort(lock, this, leafSlices[i], weight, filter, nDocs, topCollector, sort)); } int totalHits = 0; float maxScore = Float.NEGATIVE_INFINITY; @@ -458,11 +466,10 @@ maxScore = Math.max(maxScore, topFieldDocs.getMaxScore()); } } - final ScoreDoc[] scoreDocs = new ScoreDoc[hq.size()]; - for (int i = hq.size() - 1; i >= 0; i--) // put docs in array - scoreDocs[i] = hq.pop(); - return new TopFieldDocs(totalHits, scoreDocs, hq.getFields(), maxScore); + final TopFieldDocs topDocs = (TopFieldDocs) topCollector.topDocs(); + + return new TopFieldDocs(totalHits, topDocs.scoreDocs, topDocs.fields, topDocs.getMaxScore()); } } @@ -721,12 +728,13 @@ private final Weight weight; private final Filter filter; private final int nDocs; - private final FieldDocSortedHitQueue hq; + //private final FieldDocSortedHitQueue hq; + private final TopFieldCollector hq; private final Sort sort; private final LeafSlice slice; public SearcherCallableWithSort(Lock lock, IndexSearcher searcher, LeafSlice slice, Weight weight, - Filter filter, int nDocs, FieldDocSortedHitQueue hq, Sort sort) { + Filter filter, int nDocs, TopFieldCollector hq, Sort sort) { this.lock = lock; this.searcher = searcher; this.weight = weight; @@ -737,27 +745,58 @@ this.slice = slice; } + private final class FakeScorer extends Scorer { + float score; + int doc; + + public FakeScorer() { + super(null); + } + + @Override + public int advance(int target) { + throw new UnsupportedOperationException(); + } + + @Override + public int docID() { + return doc; + } + + @Override + public float freq() { + throw new UnsupportedOperationException(); + } + + @Override + public int nextDoc() { + throw new UnsupportedOperationException(); + } + + @Override + public float score() { + return score; + } + } + + private final FakeScorer fakeScorer = new FakeScorer(); + public TopFieldDocs call() throws IOException { + assert slice.leaves.length == 1; final TopFieldDocs docs = searcher.search (slice.leaves, weight, filter, nDocs, sort, true); lock.lock(); try { - hq.setFields(docs.fields); + final int base = slice.leaves[0].docBase; + hq.setNextReader(slice.leaves[0]); + hq.setScorer(fakeScorer); + for(ScoreDoc scoreDoc : docs.scoreDocs) { + fakeScorer.doc = scoreDoc.doc - base; + fakeScorer.score = scoreDoc.score; + hq.collect(scoreDoc.doc-base); + } } finally { lock.unlock(); } - - final ScoreDoc[] scoreDocs = docs.scoreDocs; - for (int j = 0; j < scoreDocs.length; j++) { // merge scoreDocs into hq - final FieldDoc fieldDoc = (FieldDoc) scoreDocs[j]; - //it would be so nice if we had a thread-safe insert - lock.lock(); - try { - if (fieldDoc == hq.insertWithOverflow(fieldDoc)) - break; - } finally { - lock.unlock(); - } - } return docs; } } Index: lucene/src/test/org/apache/lucene/search/TestSort.java --- lucene/src/test/org/apache/lucene/search/TestSort.java Mon Feb 28 08:24:50 2011 -0500 +++ lucene/src/test/org/apache/lucene/search/TestSort.java Mon Feb 28 11:11:18 2011 -0500 @@ -495,13 +495,15 @@ bottomValue = slotValues[bottom]; } + private static final FieldCache.IntParser testIntParser = new FieldCache.IntParser() { + public final int parseInt(final BytesRef term) { + return (term.bytes[term.offset]-'A') * 123456; + } + }; + @Override public FieldComparator setNextReader(AtomicReaderContext context) throws IOException { - docValues = FieldCache.DEFAULT.getInts(context.reader, "parser", new FieldCache.IntParser() { - public final int parseInt(final BytesRef term) { - return (term.bytes[term.offset]-'A') * 123456; - } - }); + docValues = FieldCache.DEFAULT.getInts(context.reader, "parser", testIntParser); return this; }