Index: lucene/join/src/test/org/apache/lucene/search/join/TestBlockJoin.java
===================================================================
--- lucene/join/src/test/org/apache/lucene/search/join/TestBlockJoin.java	(revision 1344341)
+++ lucene/join/src/test/org/apache/lucene/search/join/TestBlockJoin.java	(working copy)
@@ -103,11 +103,12 @@
     fullQuery.add(new BooleanClause(parentQuery, Occur.MUST));
     fullQuery.add(new BooleanClause(childJoinQuery, Occur.MUST));
 
-    ToParentBlockJoinCollector c = new ToParentBlockJoinCollector(Sort.RELEVANCE, 1, true, false);
+    ToParentBlockJoinCollector c = new ToParentBlockJoinCollector(Sort.RELEVANCE, 1, true, true);
 
     s.search(fullQuery, c);
     
     TopGroups<Integer> results = c.getTopGroups(childJoinQuery, null, 0, 10, 0, true);
+    assertFalse(Float.isNaN(results.maxScore));
 
     //assertEquals(1, results.totalHitCount);
     assertEquals(1, results.totalGroupedHitCount);
@@ -115,6 +116,7 @@
 
     final GroupDocs<Integer> group = results.groups[0];
     assertEquals(1, group.totalHits);
+    assertFalse(Float.isNaN(group.score));
 
     Document childDoc = s.doc(group.scoreDocs[0].doc);
     //System.out.println("  doc=" + group.scoreDocs[0].doc);
Index: lucene/join/src/java/org/apache/lucene/search/join/ToParentBlockJoinCollector.java
===================================================================
--- lucene/join/src/java/org/apache/lucene/search/join/ToParentBlockJoinCollector.java	(revision 1344341)
+++ lucene/join/src/java/org/apache/lucene/search/join/ToParentBlockJoinCollector.java	(working copy)
@@ -108,6 +108,9 @@
     // only collector
     this.sort = sort;
     this.trackMaxScore = trackMaxScore;
+    if (trackMaxScore) {
+      maxScore = Float.MIN_VALUE;
+    }
     this.trackScores = trackScores;
     this.numParentHits = numParentHits;
     queue = FieldValueHitQueue.create(sort.getSort(), numParentHits);
@@ -146,9 +149,7 @@
 
     if (trackMaxScore) {
       score = scorer.score();
-      if (score > maxScore) {
-        maxScore = score;
-      }
+      maxScore = Math.max(maxScore, score);
     }
 
     // TODO: we could sweep all joinScorers here and
@@ -202,7 +203,11 @@
       for (int i = 0; i < comparators.length; i++) {
         comparators[i].copy(comparatorSlot, parentDoc);
       }
-      //System.out.println("  startup: new OG doc=" + (docBase+parentDoc));
+      //System.out.println("  startup: new OG doc=" +
+      //(docBase+parentDoc));
+      if (!trackMaxScore && trackScores) {
+        score = scorer.score();
+      }
       final OneGroup og = new OneGroup(comparatorSlot, docBase+parentDoc, score, joinScorers.length, trackScores);
       og.readerContext = currentReaderContext;
       copyGroups(og);
@@ -431,7 +436,8 @@
 
       final TopDocs topDocs = collector.topDocs(withinGroupOffset, maxDocsPerGroup);
 
-      groups[groupIDX-offset] = new GroupDocs<Integer>(topDocs.getMaxScore(),
+      groups[groupIDX-offset] = new GroupDocs<Integer>(og.score,
+                                                       topDocs.getMaxScore(),
                                                        og.counts[slot],
                                                        topDocs.scoreDocs,
                                                        og.doc,
@@ -440,7 +446,15 @@
 
     return new TopGroups<Integer>(new TopGroups<Integer>(sort.getSort(),
                                                          withinGroupSort == null ? null : withinGroupSort.getSort(),
-                                                         0, totalGroupedHitCount, groups),
+                                                         0, totalGroupedHitCount, groups, maxScore),
                                   totalHitCount);
   }
+
+  /** Returns the highest score across all collected parent
+   *  hits, as long as <code>trackMaxScores=true</code> was passed {@link
+   *  #ToParentBlockJoinCollector on construction}.  Else,
+   *  this returns <code>Float.NaN</code> */
+  public float getMaxScore() {
+    return maxScore;
+  }
 }
Index: lucene/CHANGES.txt
===================================================================
--- lucene/CHANGES.txt	(revision 1344341)
+++ lucene/CHANGES.txt	(working copy)
@@ -1015,6 +1015,9 @@
 * LUCENE-4079: Fixed loading of Hunspell dictionaries that use aliasing (AF rules)
   (Ludovic Boutros via Chris Male)
 
+* LUCENE-4077: Expose the max score and per-group scores from
+  ToParentBlockJoinCollector (Christoph Kaser, Mike McCandless)
+
 Documentation
 
 * LUCENE-3958: Javadocs corrections for IndexWriter.
Index: lucene/grouping/src/test/org/apache/lucene/search/grouping/TestGrouping.java
===================================================================
--- lucene/grouping/src/test/org/apache/lucene/search/grouping/TestGrouping.java	(revision 1344341)
+++ lucene/grouping/src/test/org/apache/lucene/search/grouping/TestGrouping.java	(working copy)
@@ -129,10 +129,11 @@
     final AbstractFirstPassGroupingCollector<?> c1 = createRandomFirstPassCollector(groupField, groupSort, 10, canUseIDV);
     indexSearcher.search(new TermQuery(new Term("content", "random")), c1);
 
-    final AbstractSecondPassGroupingCollector<?> c2 = createSecondPassCollector(c1, groupField, groupSort, null, 0, 5, true, false, true);
+    final AbstractSecondPassGroupingCollector<?> c2 = createSecondPassCollector(c1, groupField, groupSort, null, 0, 5, true, true, true);
     indexSearcher.search(new TermQuery(new Term("content", "random")), c2);
 
     final TopGroups<?> groups = c2.getTopGroups(0);
+    assertFalse(Float.isNaN(groups.maxScore));
 
     assertEquals(7, groups.totalHitCount);
     assertEquals(7, groups.totalGroupedHitCount);
@@ -341,9 +342,9 @@
       List<GroupDocs<BytesRef>> groups = new ArrayList<GroupDocs<BytesRef>>(mvalTopGroups.groups.length);
       for (GroupDocs<MutableValue> mvalGd : mvalTopGroups.groups) {
         BytesRef groupValue = mvalGd.groupValue.exists() ? ((MutableValueStr) mvalGd.groupValue).value : null;
-        groups.add(new GroupDocs<BytesRef>(mvalGd.maxScore, mvalGd.totalHits, mvalGd.scoreDocs, groupValue, mvalGd.groupSortValues));
+        groups.add(new GroupDocs<BytesRef>(Float.NaN, mvalGd.maxScore, mvalGd.totalHits, mvalGd.scoreDocs, groupValue, mvalGd.groupSortValues));
       }
-      return new TopGroups<BytesRef>(mvalTopGroups.groupSort, mvalTopGroups.withinGroupSort, mvalTopGroups.totalHitCount, mvalTopGroups.totalGroupedHitCount, groups.toArray(new GroupDocs[groups.size()]));
+      return new TopGroups<BytesRef>(mvalTopGroups.groupSort, mvalTopGroups.withinGroupSort, mvalTopGroups.totalHitCount, mvalTopGroups.totalGroupedHitCount, groups.toArray(new GroupDocs[groups.size()]), Float.NaN);
     } else if (DVSecondPassGroupingCollector.class.isAssignableFrom(c.getClass())) {
       return ((DVSecondPassGroupingCollector<BytesRef>) c).getTopGroups(withinGroupOffset);
     }
@@ -541,20 +542,21 @@
         hits = new ScoreDoc[0];
       }
 
-      result[idx-groupOffset] = new GroupDocs<BytesRef>(0.0f,
-                                              docs.size(),
-                                              hits,
-                                              group,
-                                              fillFields ? sortedGroupFields.get(idx) : null);
+      result[idx-groupOffset] = new GroupDocs<BytesRef>(Float.NaN,
+                                                        0.0f,
+                                                        docs.size(),
+                                                        hits,
+                                                        group,
+                                                        fillFields ? sortedGroupFields.get(idx) : null);
     }
 
     if (doAllGroups) {
       return new TopGroups<BytesRef>(
-          new TopGroups<BytesRef>(groupSort.getSort(), docSort.getSort(), totalHitCount, totalGroupedHitCount, result),
-          knownGroups.size()
+                                     new TopGroups<BytesRef>(groupSort.getSort(), docSort.getSort(), totalHitCount, totalGroupedHitCount, result, Float.NaN),
+                                     knownGroups.size()
       );
     } else {
-      return new TopGroups<BytesRef>(groupSort.getSort(), docSort.getSort(), totalHitCount, totalGroupedHitCount, result);
+      return new TopGroups<BytesRef>(groupSort.getSort(), docSort.getSort(), totalHitCount, totalGroupedHitCount, result, Float.NaN);
     }
   }
 
@@ -1237,7 +1239,7 @@
         }
       }
 
-      TopGroups<BytesRef> mergedGroups = TopGroups.merge(shardTopGroups, groupSort, docSort, docOffset, topNDocs);
+      TopGroups<BytesRef> mergedGroups = TopGroups.merge(shardTopGroups, groupSort, docSort, docOffset, topNDocs, TopGroups.ScoreMergeMode.None);
       if (VERBOSE) {
         System.out.println(" " + mergedGroups.groups.length + " merged groups:");
         for(GroupDocs<BytesRef> group : mergedGroups.groups) {
Index: lucene/grouping/src/java/org/apache/lucene/search/grouping/TopGroups.java
===================================================================
--- lucene/grouping/src/java/org/apache/lucene/search/grouping/TopGroups.java	(revision 1344341)
+++ lucene/grouping/src/java/org/apache/lucene/search/grouping/TopGroups.java	(working copy)
@@ -46,13 +46,18 @@
   /** How docs are sorted within each group */
   public final SortField[] withinGroupSort;
 
-  public TopGroups(SortField[] groupSort, SortField[] withinGroupSort, int totalHitCount, int totalGroupedHitCount, GroupDocs<GROUP_VALUE_TYPE>[] groups) {
+  /** Highest score across all hits, or
+   *  <code>Float.NaN</code> if scores were not computed. */
+  public final float maxScore;
+
+  public TopGroups(SortField[] groupSort, SortField[] withinGroupSort, int totalHitCount, int totalGroupedHitCount, GroupDocs<GROUP_VALUE_TYPE>[] groups, float maxScore) {
     this.groupSort = groupSort;
     this.withinGroupSort = withinGroupSort;
     this.totalHitCount = totalHitCount;
     this.totalGroupedHitCount = totalGroupedHitCount;
     this.groups = groups;
     this.totalGroupCount = null;
+    this.maxScore = maxScore;
   }
 
   public TopGroups(TopGroups<GROUP_VALUE_TYPE> oldTopGroups, Integer totalGroupCount) {
@@ -61,9 +66,20 @@
     this.totalHitCount = oldTopGroups.totalHitCount;
     this.totalGroupedHitCount = oldTopGroups.totalGroupedHitCount;
     this.groups = oldTopGroups.groups;
+    this.maxScore = oldTopGroups.maxScore;
     this.totalGroupCount = totalGroupCount;
   }
 
+  /** How the GroupDocs score (if any) should be merged. */
+  public enum ScoreMergeMode {
+    /** Set score to Float.NaN */
+    None,     
+    /* Sum score across all shards for this group. */
+    Total,
+    /* Avg score across all shards for this group. */
+    Avg,
+  };
+
   /** Merges an array of TopGroups, for example obtained
    *  from the second-pass collector across multiple
    *  shards.  Each TopGroups must have been sorted by the
@@ -81,7 +97,7 @@
    * <b>NOTE</b>: the topDocs in each GroupDocs is actually
    * an instance of TopDocsAndShards
    */
-  public static <T> TopGroups<T> merge(TopGroups<T>[] shardGroups, Sort groupSort, Sort docSort, int docOffset, int docTopN)
+  public static <T> TopGroups<T> merge(TopGroups<T>[] shardGroups, Sort groupSort, Sort docSort, int docOffset, int docTopN, ScoreMergeMode scoreMergeMode)
     throws IOException {
 
     //System.out.println("TopGroups.merge");
@@ -115,12 +131,14 @@
     final GroupDocs<T>[] mergedGroupDocs = new GroupDocs[numGroups];
 
     final TopDocs[] shardTopDocs = new TopDocs[shardGroups.length];
+    float totalMaxScore = Float.MIN_VALUE;
 
     for(int groupIDX=0;groupIDX<numGroups;groupIDX++) {
       final T groupValue = shardGroups[0].groups[groupIDX].groupValue;
       //System.out.println("  merge groupValue=" + groupValue + " sortValues=" + Arrays.toString(shardGroups[0].groups[groupIDX].groupSortValues));
       float maxScore = Float.MIN_VALUE;
       int totalHits = 0;
+      double scoreSum = 0.0;
       for(int shardIDX=0;shardIDX<shardGroups.length;shardIDX++) {
         //System.out.println("    shard=" + shardIDX);
         final TopGroups<T> shard = shardGroups[shardIDX];
@@ -144,6 +162,7 @@
                                              shardGroupDocs.maxScore);
         maxScore = Math.max(maxScore, shardGroupDocs.maxScore);
         totalHits += shardGroupDocs.totalHits;
+        scoreSum += shardGroupDocs.score;
       }
 
       final TopDocs mergedTopDocs = TopDocs.merge(docSort, docOffset + docTopN, shardTopDocs);
@@ -162,12 +181,34 @@
                          0,
                          mergedTopDocs.scoreDocs.length - docOffset);
       }
+
+      final float groupScore;
+      switch(scoreMergeMode) {
+      case None:
+        groupScore = Float.NaN;
+        break;
+      case Avg:
+        if (totalHits > 0) {
+          groupScore = (float) (scoreSum / totalHits);
+        } else {
+          groupScore = Float.NaN;
+        }
+        break;
+      case Total:
+        groupScore = (float) scoreSum;
+        break;
+      default:
+        throw new IllegalArgumentException("can't handle ScoreMergeMode " + scoreMergeMode);
+      }
+        
       //System.out.println("SHARDS=" + Arrays.toString(mergedTopDocs.shardIndex));
-      mergedGroupDocs[groupIDX] = new GroupDocs<T>(maxScore,
+      mergedGroupDocs[groupIDX] = new GroupDocs<T>(groupScore,
+                                                   maxScore,
                                                    totalHits,
                                                    mergedScoreDocs,
                                                    groupValue,
                                                    shardGroups[0].groups[groupIDX].groupSortValues);
+      totalMaxScore = Math.max(totalMaxScore, maxScore);
     }
 
     if (totalGroupCount != null) {
@@ -175,14 +216,16 @@
                               docSort == null ? null : docSort.getSort(),
                               totalHitCount,
                               totalGroupedHitCount,
-                              mergedGroupDocs);
+                              mergedGroupDocs,
+                              totalMaxScore);
       return new TopGroups<T>(result, totalGroupCount);
     } else {
       return new TopGroups<T>(groupSort.getSort(),
                               docSort == null ? null : docSort.getSort(),
                               totalHitCount,
                               totalGroupedHitCount,
-                              mergedGroupDocs);
+                              mergedGroupDocs,
+                              totalMaxScore);
     }
   }
 }
Index: lucene/grouping/src/java/org/apache/lucene/search/grouping/GroupingSearch.java
===================================================================
--- lucene/grouping/src/java/org/apache/lucene/search/grouping/GroupingSearch.java	(revision 1344341)
+++ lucene/grouping/src/java/org/apache/lucene/search/grouping/GroupingSearch.java	(working copy)
@@ -246,7 +246,7 @@
 
     Collection<SearchGroup> topSearchGroups = firstPassCollector.getTopGroups(groupOffset, fillSortFields);
     if (topSearchGroups == null) {
-      return new TopGroups(new SortField[0], new SortField[0], 0, 0, new GroupDocs[0]);
+      return new TopGroups(new SortField[0], new SortField[0], 0, 0, new GroupDocs[0], Float.NaN);
     }
 
     int topNInsideGroup = groupDocsOffset + groupDocsLimit;
Index: lucene/grouping/src/java/org/apache/lucene/search/grouping/GroupDocs.java
===================================================================
--- lucene/grouping/src/java/org/apache/lucene/search/grouping/GroupDocs.java	(revision 1344341)
+++ lucene/grouping/src/java/org/apache/lucene/search/grouping/GroupDocs.java	(working copy)
@@ -30,6 +30,10 @@
   /** Max score in this group */
   public final float maxScore;
 
+  /** Overall aggregated score of this group (currently only
+   *  set by join queries). */
+  public final float score;
+
   /** Hits; this may be {@link
    * org.apache.lucene.search.FieldDoc} instances if the
    * withinGroupSort sorted by fields. */
@@ -42,11 +46,13 @@
    *  AbstractFirstPassGroupingCollector}. */
   public final Object[] groupSortValues;
 
-  public GroupDocs(float maxScore,
+  public GroupDocs(float score,
+                   float maxScore,
                    int totalHits,
                    ScoreDoc[] scoreDocs,
                    GROUP_VALUE_TYPE groupValue,
                    Object[] groupSortValues) {
+    this.score = score;
     this.maxScore = maxScore;
     this.totalHits = totalHits;
     this.scoreDocs = scoreDocs;
Index: lucene/grouping/src/java/org/apache/lucene/search/grouping/AbstractSecondPassGroupingCollector.java
===================================================================
--- lucene/grouping/src/java/org/apache/lucene/search/grouping/AbstractSecondPassGroupingCollector.java	(revision 1344341)
+++ lucene/grouping/src/java/org/apache/lucene/search/grouping/AbstractSecondPassGroupingCollector.java	(working copy)
@@ -124,19 +124,23 @@
     final GroupDocs<GROUP_VALUE_TYPE>[] groupDocsResult = (GroupDocs<GROUP_VALUE_TYPE>[]) new GroupDocs[groups.size()];
 
     int groupIDX = 0;
+    float maxScore = Float.MIN_VALUE;
     for(SearchGroup<?> group : groups) {
       final SearchGroupDocs<GROUP_VALUE_TYPE> groupDocs = groupMap.get(group.groupValue);
       final TopDocs topDocs = groupDocs.collector.topDocs(withinGroupOffset, maxDocsPerGroup);
-      groupDocsResult[groupIDX++] = new GroupDocs<GROUP_VALUE_TYPE>(topDocs.getMaxScore(),
+      groupDocsResult[groupIDX++] = new GroupDocs<GROUP_VALUE_TYPE>(Float.NaN,
+                                                                    topDocs.getMaxScore(),
                                                                     topDocs.totalHits,
                                                                     topDocs.scoreDocs,
                                                                     groupDocs.groupValue,
                                                                     group.sortValues);
+      maxScore = Math.max(maxScore, topDocs.getMaxScore());
     }
 
     return new TopGroups<GROUP_VALUE_TYPE>(groupSort.getSort(),
                                            withinGroupSort == null ? null : withinGroupSort.getSort(),
-                                           totalHitCount, totalGroupedHitCount, groupDocsResult);
+                                           totalHitCount, totalGroupedHitCount, groupDocsResult,
+                                           maxScore);
   }
 
 
Index: lucene/grouping/src/java/org/apache/lucene/search/grouping/BlockGroupingCollector.java
===================================================================
--- lucene/grouping/src/java/org/apache/lucene/search/grouping/BlockGroupingCollector.java	(revision 1344341)
+++ lucene/grouping/src/java/org/apache/lucene/search/grouping/BlockGroupingCollector.java	(working copy)
@@ -307,6 +307,8 @@
 
     final FakeScorer fakeScorer = new FakeScorer();
 
+    float maxScore = Float.MIN_VALUE;
+
     @SuppressWarnings({"unchecked","rawtypes"})
     final GroupDocs<Object>[] groups = new GroupDocs[groupQueue.size() - groupOffset];
     for(int downTo=groupQueue.size()-groupOffset-1;downTo>=0;downTo--) {
@@ -351,11 +353,15 @@
 
       final TopDocs topDocs = collector.topDocs(withinGroupOffset, maxDocsPerGroup);
 
-      groups[downTo] = new GroupDocs<Object>(topDocs.getMaxScore(),
-                                     og.count,
-                                     topDocs.scoreDocs,
-                                     null,
-                                     groupSortValues);
+      // TODO: we could aggregate scores across children
+      // by Sum/Avg instead of passing NaN:
+      groups[downTo] = new GroupDocs<Object>(Float.NaN,
+                                             topDocs.getMaxScore(),
+                                             og.count,
+                                             topDocs.scoreDocs,
+                                             null,
+                                             groupSortValues);
+      maxScore = Math.max(maxScore, topDocs.getMaxScore());
     }
 
     /*
@@ -368,7 +374,7 @@
 
     return new TopGroups<Object>(new TopGroups<Object>(groupSort.getSort(),
                                        withinGroupSort == null ? null : withinGroupSort.getSort(),
-                                       totalHitCount, totalGroupedHitCount, groups),
+                                       totalHitCount, totalGroupedHitCount, groups, maxScore),
                          totalGroupCount);
   }
 
Index: solr/core/src/java/org/apache/solr/search/grouping/distributed/shardresultserializer/TopGroupsResultTransformer.java
===================================================================
--- solr/core/src/java/org/apache/solr/search/grouping/distributed/shardresultserializer/TopGroupsResultTransformer.java	(revision 1344341)
+++ solr/core/src/java/org/apache/solr/search/grouping/distributed/shardresultserializer/TopGroupsResultTransformer.java	(working copy)
@@ -142,13 +142,13 @@
         }
 
         BytesRef groupValueRef = groupValue != null ? new BytesRef(groupValue) : null;
-        groupDocs.add(new GroupDocs<BytesRef>(maxScore, totalGroupHits, scoreDocs, groupValueRef, null));
+        groupDocs.add(new GroupDocs<BytesRef>(Float.NaN, maxScore, totalGroupHits, scoreDocs, groupValueRef, null));
       }
 
       @SuppressWarnings("unchecked")
       GroupDocs<BytesRef>[] groupDocsArr = groupDocs.toArray(new GroupDocs[groupDocs.size()]);
       TopGroups<BytesRef> topGroups = new TopGroups<BytesRef>(
-        groupSort.getSort(), sortWithinGroup.getSort(), totalHitCount, totalGroupedHitCount, groupDocsArr
+           groupSort.getSort(), sortWithinGroup.getSort(), totalHitCount, totalGroupedHitCount, groupDocsArr, Float.NaN
       );
 
       result.put(key, topGroups);
Index: solr/core/src/java/org/apache/solr/search/grouping/distributed/command/TopGroupsFieldCommand.java
===================================================================
--- solr/core/src/java/org/apache/solr/search/grouping/distributed/command/TopGroupsFieldCommand.java	(revision 1344341)
+++ solr/core/src/java/org/apache/solr/search/grouping/distributed/command/TopGroupsFieldCommand.java	(working copy)
@@ -135,7 +135,7 @@
   @SuppressWarnings("unchecked")
   public TopGroups<BytesRef> result() {
     if (firstPhaseGroups.isEmpty()) {
-      return new TopGroups<BytesRef>(groupSort.getSort(), sortWithinGroup.getSort(), 0, 0, new GroupDocs[0]);
+      return new TopGroups<BytesRef>(groupSort.getSort(), sortWithinGroup.getSort(), 0, 0, new GroupDocs[0], Float.NaN);
     }
 
     return secondPassCollector.getTopGroups(0);
Index: solr/core/src/java/org/apache/solr/search/grouping/distributed/responseprocessor/TopGroupsShardResponseProcessor.java
===================================================================
--- solr/core/src/java/org/apache/solr/search/grouping/distributed/responseprocessor/TopGroupsShardResponseProcessor.java	(revision 1344341)
+++ solr/core/src/java/org/apache/solr/search/grouping/distributed/responseprocessor/TopGroupsShardResponseProcessor.java	(working copy)
@@ -97,7 +97,7 @@
         }
 
         TopGroups<BytesRef>[] topGroupsArr = new TopGroups[topGroups.size()];
-        rb.mergedTopGroups.put(groupField, TopGroups.merge(topGroups.toArray(topGroupsArr), groupSort, sortWithinGroup, groupOffsetDefault, docsPerGroupDefault));
+        rb.mergedTopGroups.put(groupField, TopGroups.merge(topGroups.toArray(topGroupsArr), groupSort, sortWithinGroup, groupOffsetDefault, docsPerGroupDefault, TopGroups.ScoreMergeMode.None));
       }
 
       for (String query : commandTopDocs.keySet()) {
Index: solr/core/src/java/org/apache/solr/search/Grouping.java
===================================================================
--- solr/core/src/java/org/apache/solr/search/Grouping.java	(revision 1344341)
+++ solr/core/src/java/org/apache/solr/search/Grouping.java	(working copy)
@@ -858,7 +858,7 @@
     protected void finish() throws IOException {
       TopDocsCollector topDocsCollector = (TopDocsCollector) collector.getDelegate();
       TopDocs topDocs = topDocsCollector.topDocs();
-      GroupDocs<String> groupDocs = new GroupDocs<String>(topDocs.getMaxScore(), topDocs.totalHits, topDocs.scoreDocs, query.toString(), null);
+      GroupDocs<String> groupDocs = new GroupDocs<String>(Float.NaN, topDocs.getMaxScore(), topDocs.totalHits, topDocs.scoreDocs, query.toString(), null);
       if (main) {
         mainResult = getDocList(groupDocs);
       } else {
Index: solr/core/src/java/org/apache/solr/handler/component/QueryComponent.java
===================================================================
--- solr/core/src/java/org/apache/solr/handler/component/QueryComponent.java	(revision 1344341)
+++ solr/core/src/java/org/apache/solr/handler/component/QueryComponent.java	(working copy)
@@ -652,7 +652,7 @@
     GroupingSpecification groupSpec = rb.getGroupingSpec();
     if (rb.mergedTopGroups.isEmpty()) {
       for (String field : groupSpec.getFields()) {
-        rb.mergedTopGroups.put(field, new TopGroups(null, null, 0, 0, new GroupDocs[]{}));
+        rb.mergedTopGroups.put(field, new TopGroups(null, null, 0, 0, new GroupDocs[]{}, Float.NaN));
       }
       rb.resultIds = new HashMap<Object, ShardDoc>();
     }
