Index: org/apache/lucene/search/FieldDocSortedHitQueue.java =================================================================== --- org/apache/lucene/search/FieldDocSortedHitQueue.java (revision 347953) +++ org/apache/lucene/search/FieldDocSortedHitQueue.java (working copy) @@ -93,7 +93,30 @@ return ret; } + /** Stores the maximum score value encountered, needed for normalizing. */ + protected float maxscore = Float.NEGATIVE_INFINITY; + /** returns the maximum score encountered by elements inserted via insert() + */ + public float getMaxScore() { + return maxscore; + } + + // The signature of this method takes a FieldDoc in order to avoid + // the unneeded cast to retrieve the score. + // inherit javadoc + public boolean insert(FieldDoc fdoc) { + maxscore = Math.max(maxscore,fdoc.score); + return super.insert(fdoc); + } + + // This overrides PriorityQueue.insert() so that insert(FieldDoc) that + // keeps track of the score isn't accidentally bypassed. + // inherit javadoc + public boolean insert(Object fdoc) { + return insert((FieldDoc)fdoc); + } + /** * Returns whether a is less relevant than b. * @param a ScoreDoc Index: org/apache/lucene/search/FieldSortedHitQueue.java =================================================================== --- org/apache/lucene/search/FieldSortedHitQueue.java (revision 347953) +++ org/apache/lucene/search/FieldSortedHitQueue.java (working copy) @@ -132,7 +132,7 @@ for (int i=0; i 1.0f) doc.score /= maxscore; // normalize scores + //if (maxscore > 1.0f) doc.score /= maxscore; // normalize scores return doc; } Index: org/apache/lucene/search/Hits.java =================================================================== --- org/apache/lucene/search/Hits.java (revision 347953) +++ org/apache/lucene/search/Hits.java (working copy) @@ -67,8 +67,9 @@ ScoreDoc[] scoreDocs = topDocs.scoreDocs; float scoreNorm = 1.0f; - if (length > 0 && scoreDocs[0].score > 1.0f) { - scoreNorm = 1.0f / scoreDocs[0].score; + + if (length > 0 && topDocs.maxScore > 1.0f) { + scoreNorm = 1.0f / topDocs.maxScore; } int end = scoreDocs.length < length ? scoreDocs.length : length; Index: org/apache/lucene/search/IndexSearcher.java =================================================================== --- org/apache/lucene/search/IndexSearcher.java (revision 347953) +++ org/apache/lucene/search/IndexSearcher.java (working copy) @@ -97,7 +97,7 @@ Scorer scorer = weight.scorer(reader); if (scorer == null) - return new TopDocs(0, new ScoreDoc[0]); + return new TopDocs(0, new ScoreDoc[0], Float.NEGATIVE_INFINITY); final BitSet bits = filter != null ? filter.bits(reader) : null; final HitQueue hq = new HitQueue(nDocs); @@ -120,7 +120,9 @@ for (int i = hq.size()-1; i >= 0; i--) // put docs in array scoreDocs[i] = (ScoreDoc)hq.pop(); - return new TopDocs(totalHits[0], scoreDocs); + float maxScore = (totalHits[0]==0) ? Float.NEGATIVE_INFINITY : scoreDocs[0].score; + + return new TopDocs(totalHits[0], scoreDocs, maxScore); } // inherit javadoc @@ -129,7 +131,7 @@ throws IOException { Scorer scorer = weight.scorer(reader); if (scorer == null) - return new TopFieldDocs(0, new ScoreDoc[0], sort.fields); + return new TopFieldDocs(0, new ScoreDoc[0], sort.fields, Float.NEGATIVE_INFINITY); final BitSet bits = filter != null ? filter.bits(reader) : null; final FieldSortedHitQueue hq = @@ -149,7 +151,7 @@ for (int i = hq.size()-1; i >= 0; i--) // put docs in array scoreDocs[i] = hq.fillFields ((FieldDoc) hq.pop()); - return new TopFieldDocs(totalHits[0], scoreDocs, hq.getFields()); + return new TopFieldDocs(totalHits[0], scoreDocs, hq.getFields(), hq.getMaxScore()); } // inherit javadoc Index: org/apache/lucene/search/MultiSearcher.java =================================================================== --- org/apache/lucene/search/MultiSearcher.java (revision 347953) +++ org/apache/lucene/search/MultiSearcher.java (working copy) @@ -208,8 +208,10 @@ ScoreDoc[] scoreDocs = new ScoreDoc[hq.size()]; for (int i = hq.size()-1; i >= 0; i--) // put docs in array scoreDocs[i] = (ScoreDoc)hq.pop(); - - return new TopDocs(totalHits, scoreDocs); + + float maxScore = (totalHits==0) ? Float.NEGATIVE_INFINITY : scoreDocs[0].score; + + return new TopDocs(totalHits, scoreDocs, maxScore); } public TopFieldDocs search (Weight weight, Filter filter, int n, Sort sort) @@ -219,6 +221,7 @@ 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); totalHits += docs.totalHits; // update totalHits ScoreDoc[] scoreDocs = docs.scoreDocs; @@ -234,7 +237,7 @@ for (int i = hq.size() - 1; i >= 0; i--) // put docs in array scoreDocs[i] = (ScoreDoc) hq.pop(); - return new TopFieldDocs (totalHits, scoreDocs, hq.getFields()); + return new TopFieldDocs (totalHits, scoreDocs, hq.getFields(), hq.getMaxScore()); } Index: org/apache/lucene/search/ParallelMultiSearcher.java =================================================================== --- org/apache/lucene/search/ParallelMultiSearcher.java (revision 347953) +++ org/apache/lucene/search/ParallelMultiSearcher.java (working copy) @@ -90,7 +90,9 @@ for (int i = hq.size() - 1; i >= 0; i--) // put docs in array scoreDocs[i] = (ScoreDoc) hq.pop(); - return new TopDocs(totalHits, scoreDocs); + float maxScore = (totalHits==0) ? Float.NEGATIVE_INFINITY : scoreDocs[0].score; + + return new TopDocs(totalHits, scoreDocs, maxScore); } /** @@ -139,7 +141,7 @@ for (int i = hq.size() - 1; i >= 0; i--) // put docs in array scoreDocs[i] = (ScoreDoc) hq.pop(); - return new TopFieldDocs(totalHits, scoreDocs, hq.getFields()); + return new TopFieldDocs(totalHits, scoreDocs, hq.getFields(), hq.getMaxScore()); } /** Lower-level search API. Index: org/apache/lucene/search/TopDocs.java =================================================================== --- org/apache/lucene/search/TopDocs.java (revision 347953) +++ org/apache/lucene/search/TopDocs.java (working copy) @@ -25,10 +25,13 @@ public int totalHits; /** Expert: The top hits for the query. */ public ScoreDoc[] scoreDocs; - + /** Stores the maximum score value encountered, needed for normalizing. */ + public float maxScore; + /** Expert: Constructs a TopDocs.*/ - TopDocs(int totalHits, ScoreDoc[] scoreDocs) { + TopDocs(int totalHits, ScoreDoc[] scoreDocs, float maxScore) { this.totalHits = totalHits; this.scoreDocs = scoreDocs; + this.maxScore = maxScore; } } Index: org/apache/lucene/search/TopFieldDocs.java =================================================================== --- org/apache/lucene/search/TopFieldDocs.java (revision 347953) +++ org/apache/lucene/search/TopFieldDocs.java (working copy) @@ -32,14 +32,14 @@ /** The fields which were used to sort results by. */ public SortField[] fields; - + /** Creates one of these objects. * @param totalHits Total number of hits for the query. * @param scoreDocs The top hits for the query. * @param fields The sort criteria used to find the top hits. */ - TopFieldDocs (int totalHits, ScoreDoc[] scoreDocs, SortField[] fields) { - super (totalHits, scoreDocs); + TopFieldDocs (int totalHits, ScoreDoc[] scoreDocs, SortField[] fields, float maxScore) { + super (totalHits, scoreDocs, maxScore); this.fields = fields; } } \ No newline at end of file