Index: src/java/org/apache/lucene/search/FieldDocSortedHitQueue.java
===================================================================
--- src/java/org/apache/lucene/search/FieldDocSortedHitQueue.java (revision 721755)
+++ src/java/org/apache/lucene/search/FieldDocSortedHitQueue.java (working copy)
@@ -93,6 +93,9 @@
return ret;
}
+ protected FieldDoc asFieldDoc (Object obj) {
+ return (FieldDoc)obj;
+ }
/**
* Returns whether a is less relevant than b.
@@ -100,9 +103,9 @@
* @param b ScoreDoc
* @return true if document a should be sorted after document b.
*/
- protected final boolean lessThan (final Object a, final Object b) {
- final FieldDoc docA = (FieldDoc) a;
- final FieldDoc docB = (FieldDoc) b;
+ protected boolean lessThan (final Object a, final Object b) {
+ final FieldDoc docA = asFieldDoc(a);
+ final FieldDoc docB = asFieldDoc(b);
final int n = fields.length;
int c = 0;
for (int i=0; i hitB.score;
+ }
+ }
+ }
+
public TopDocs search(Weight weight, Filter filter, int nDocs)
throws IOException {
- HitQueue hq = new HitQueue(nDocs);
+ SubsearcherHitQueue shq = new SubsearcherHitQueue(searchables.length);
int totalHits = 0;
for (int i = 0; i < searchables.length; i++) { // search each searcher
TopDocs docs = searchables[i].search(weight, filter, nDocs);
totalHits += docs.totalHits; // update totalHits
- ScoreDoc[] scoreDocs = docs.scoreDocs;
- for (int j = 0; j < scoreDocs.length; j++) { // merge scoreDocs into hq
- ScoreDoc scoreDoc = scoreDocs[j];
- scoreDoc.doc += starts[i]; // convert doc
- if(!hq.insert(scoreDoc))
- break; // no more scores > minScore
+ if (docs.totalHits > 0) {
+ final SubsearcherTopDocs subsearcherTopDocs = new SubsearcherTopDocs(docs, i);
+ subsearcherTopDocs.convertTopDoc(starts);
+ shq.put(subsearcherTopDocs);
}
}
- ScoreDoc[] scoreDocs = new ScoreDoc[hq.size()];
- for (int i = hq.size()-1; i >= 0; i--) // put docs in array
- scoreDocs[i] = (ScoreDoc)hq.pop();
-
+ // merge top nDocs sorted results into scoreDocs
+ ScoreDoc[] scoreDocs = new ScoreDoc[Math.min(totalHits, nDocs)];
+
+ for (int i = 0; i < scoreDocs.length; i++) {
+ // using the top(), top().change(), adjustTop() optimized form
+ final SubsearcherTopDocs topSubsearcherHits = (SubsearcherTopDocs) shq.top();
+ final ScoreDoc topDoc = topSubsearcherHits.topDoc();
+ scoreDocs[i] = topDoc;
+
+ topSubsearcherHits.hitIdx++;
+
+ if (topSubsearcherHits.hasNext()) {
+ topSubsearcherHits.convertTopDoc(starts);
+ shq.adjustTop();
+ } else {
+ shq.pop();
+ }
+ }
+
float maxScore = (totalHits==0) ? Float.NEGATIVE_INFINITY : scoreDocs[0].score;
-
+
return new TopDocs(totalHits, scoreDocs, maxScore);
}
+ static class SubsearcherFieldDocSortedHitQueue extends FieldDocSortedHitQueue {
+ SubsearcherFieldDocSortedHitQueue(SortField[] fields, int size) {
+ super(fields, size);
+ }
+
+ protected FieldDoc asFieldDoc (Object obj) {
+ final SubsearcherTopDocs subsearcherTopDocs = (SubsearcherTopDocs)obj;
+ final FieldDoc hit = (FieldDoc) subsearcherTopDocs.topDoc();
+ return hit;
+ }
+
+ protected boolean lessThan(Object a, Object b) {
+ boolean c = super.lessThan(a, b);
+ // invert lessThan to make a max top queue
+ return ! c;
+ }
+ }
+
public TopFieldDocs search (Weight weight, Filter filter, int n, Sort sort)
throws IOException {
- FieldDocSortedHitQueue hq = null;
+ SubsearcherFieldDocSortedHitQueue shq = null;
int totalHits = 0;
- float maxScore=Float.NEGATIVE_INFINITY;
-
for (int i = 0; i < searchables.length; i++) { // search each searcher
- TopFieldDocs docs = searchables[i].search (weight, filter, n, sort);
-
- if (hq == null) hq = new FieldDocSortedHitQueue (docs.fields, n);
+ TopFieldDocs docs = searchables[i].search(weight, filter, n, sort);
totalHits += docs.totalHits; // update totalHits
- maxScore = Math.max(maxScore, docs.getMaxScore());
- ScoreDoc[] scoreDocs = docs.scoreDocs;
- for (int j = 0; j < scoreDocs.length; j++) { // merge scoreDocs into hq
- ScoreDoc scoreDoc = scoreDocs[j];
- scoreDoc.doc += starts[i]; // convert doc
- if (!hq.insert (scoreDoc))
- break; // no more scores > minScore
+ if (docs.totalHits > 0) {
+ if (shq == null) shq = new SubsearcherFieldDocSortedHitQueue (docs.fields, n);
+ final SubsearcherTopDocs subsearcherTopDocs = new SubsearcherTopDocs(docs, i);
+ subsearcherTopDocs.convertTopDoc(starts);
+ shq.put(subsearcherTopDocs);
}
}
- ScoreDoc[] scoreDocs = new ScoreDoc[hq.size()];
- for (int i = hq.size() - 1; i >= 0; i--) // put docs in array
- scoreDocs[i] = (ScoreDoc) hq.pop();
+ // merge top nDocs sorted results into scoreDocs
+ ScoreDoc[] scoreDocs = new ScoreDoc[Math.min(totalHits, n)];
- return new TopFieldDocs (totalHits, scoreDocs, hq.getFields(), maxScore);
+ for (int i = 0; i < scoreDocs.length; i++) {
+ // using the top(), top().change(), adjustTop() optimized form
+ final SubsearcherTopDocs topSubsearcherHits = (SubsearcherTopDocs) shq.top();
+ final ScoreDoc topDoc = topSubsearcherHits.topDoc();
+ scoreDocs[i] = topDoc;
+
+ topSubsearcherHits.hitIdx++;
+
+ if (topSubsearcherHits.hasNext()) {
+ topSubsearcherHits.convertTopDoc(starts);
+ shq.adjustTop();
+ } else {
+ shq.pop();
+ }
+ }
+
+ float maxScore = (totalHits==0) ? Float.NEGATIVE_INFINITY : scoreDocs[0].score;
+
+ return new TopFieldDocs(totalHits, scoreDocs, shq.getFields(), maxScore);
}