Index: org/apache/lucene/search/FieldSortedHitQueue.java =================================================================== --- org/apache/lucene/search/FieldSortedHitQueue.java (revision 348171) +++ 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 348171) +++ 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.getMaxScore() > 1.0f) { + scoreNorm = 1.0f / topDocs.getMaxScore(); } int end = scoreDocs.length < length ? scoreDocs.length : length; Index: org/apache/lucene/search/IndexSearcher.java =================================================================== --- org/apache/lucene/search/IndexSearcher.java (revision 348171) +++ 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 348171) +++ 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) @@ -217,10 +219,14 @@ FieldDocSortedHitQueue hq = 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); 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]; @@ -234,7 +240,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(), maxScore); } Index: org/apache/lucene/search/ParallelMultiSearcher.java =================================================================== --- org/apache/lucene/search/ParallelMultiSearcher.java (revision 348171) +++ 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); } /** @@ -120,6 +122,8 @@ msta[i].start(); } + float maxScore=Float.NEGATIVE_INFINITY; + for (int i = 0; i < searchables.length; i++) { try { msta[i].join(); @@ -129,6 +133,7 @@ IOException ioe = msta[i].getIOException(); if (ioe == null) { totalHits += msta[i].hits(); + maxScore=Math.max(maxScore, msta[i].getMaxScore()); } else { // if one search produced an IOException, rethrow it throw ioe; @@ -139,7 +144,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(), maxScore); } /** Lower-level search API. @@ -274,6 +279,10 @@ return docs.totalHits; } + public float getMaxScore() { + return docs.getMaxScore(); + } + public IOException getIOException() { return ioe; } Index: org/apache/lucene/search/TopDocs.java =================================================================== --- org/apache/lucene/search/TopDocs.java (revision 348171) +++ org/apache/lucene/search/TopDocs.java (working copy) @@ -25,10 +25,23 @@ public int totalHits; /** Expert: The top hits for the query. */ public ScoreDoc[] scoreDocs; - + /** Expert: Stores the maximum score value encountered, needed for normalizing. */ + private float maxScore; + + /** Expert: Returns the maximum score value encountered. */ + public float getMaxScore() { + return maxScore; + } + + /** Expert: Sets the maximum score value encountered. */ + public void setMaxScore(float maxScore) { + this.maxScore=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 348171) +++ org/apache/lucene/search/TopFieldDocs.java (working copy) @@ -32,14 +32,15 @@ /** 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. + * @param maxScore The maximum score encountered. */ - 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