You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by is...@apache.org on 2020/04/06 07:35:20 UTC

[lucene-solr] 01/02: SOLR-13004: Fixing grouping overflow of matches and ngroups with large index

This is an automated email from the ASF dual-hosted git repository.

ishan pushed a commit to branch jira/solr-13004-8x
in repository https://gitbox.apache.org/repos/asf/lucene-solr.git

commit 60515796dc8f66b6c8ef7483464588bec13712c4
Author: Ishan Chattopadhyaya <is...@apache.org>
AuthorDate: Fri Apr 3 07:35:07 2020 +0530

    SOLR-13004: Fixing grouping overflow of matches and ngroups with large index
---
 .../search/grouping/BlockGroupingCollector.java    |  4 ++--
 .../lucene/search/grouping/GroupingSearch.java     |  2 +-
 .../apache/lucene/search/grouping/TopGroups.java   | 20 ++++++++---------
 .../lucene/search/grouping/TestGrouping.java       | 12 +++++-----
 .../src/java/org/apache/solr/core/SolrCore.java    |  3 +++
 .../solr/handler/component/ResponseBuilder.java    |  4 ++--
 .../java/org/apache/solr/request/SimpleFacets.java |  2 +-
 .../src/java/org/apache/solr/search/Grouping.java  | 26 +++++++++++-----------
 .../solr/search/grouping/CommandHandler.java       |  4 ++--
 .../distributed/command/QueryCommandResult.java    |  6 ++---
 .../command/SearchGroupsFieldCommand.java          |  4 ++--
 .../command/SearchGroupsFieldCommandResult.java    |  6 ++---
 .../SearchGroupShardResponseProcessor.java         | 12 +++++-----
 .../SearchGroupsResultTransformer.java             |  4 ++--
 .../TopGroupsResultTransformer.java                |  6 ++---
 .../GroupedEndResultTransformer.java               |  2 +-
 .../org/apache/solr/TestDistributedGrouping.java   |  4 ++--
 .../solr/client/solrj/response/GroupCommand.java   | 12 +++++-----
 .../solr/client/solrj/response/QueryResponse.java  |  6 ++---
 .../src/test-files/solrj/sampleGroupResponse.xml   |  4 ++--
 20 files changed, 73 insertions(+), 70 deletions(-)

diff --git a/lucene/grouping/src/java/org/apache/lucene/search/grouping/BlockGroupingCollector.java b/lucene/grouping/src/java/org/apache/lucene/search/grouping/BlockGroupingCollector.java
index 23601ca..dad1101 100644
--- a/lucene/grouping/src/java/org/apache/lucene/search/grouping/BlockGroupingCollector.java
+++ b/lucene/grouping/src/java/org/apache/lucene/search/grouping/BlockGroupingCollector.java
@@ -353,8 +353,8 @@ public class BlockGroupingCollector extends SimpleCollector {
 
     return new TopGroups<>(new TopGroups<>(groupSort.getSort(),
                                        withinGroupSort.getSort(),
-                                       totalHitCount, totalGroupedHitCount, groups, maxScore),
-                         totalGroupCount);
+                                      (long) totalHitCount, (long) totalGroupedHitCount, groups, maxScore),
+                          (long) totalGroupCount);
   }
 
   @Override
diff --git a/lucene/grouping/src/java/org/apache/lucene/search/grouping/GroupingSearch.java b/lucene/grouping/src/java/org/apache/lucene/search/grouping/GroupingSearch.java
index b88fb74..6ac5dc1 100644
--- a/lucene/grouping/src/java/org/apache/lucene/search/grouping/GroupingSearch.java
+++ b/lucene/grouping/src/java/org/apache/lucene/search/grouping/GroupingSearch.java
@@ -161,7 +161,7 @@ public class GroupingSearch {
     }
 
     if (allGroups) {
-      return new TopGroups(secondPassCollector.getTopGroups(groupDocsOffset), matchingGroups.size());
+      return new TopGroups(secondPassCollector.getTopGroups(groupDocsOffset), (long) matchingGroups.size());
     } else {
       return secondPassCollector.getTopGroups(groupDocsOffset);
     }
diff --git a/lucene/grouping/src/java/org/apache/lucene/search/grouping/TopGroups.java b/lucene/grouping/src/java/org/apache/lucene/search/grouping/TopGroups.java
index cb84400..d941a1a 100644
--- a/lucene/grouping/src/java/org/apache/lucene/search/grouping/TopGroups.java
+++ b/lucene/grouping/src/java/org/apache/lucene/search/grouping/TopGroups.java
@@ -29,13 +29,13 @@ import org.apache.lucene.search.TotalHits.Relation;
  * @lucene.experimental */
 public class TopGroups<T> {
   /** Number of documents matching the search */
-  public final int totalHitCount;
+  public final long totalHitCount;
 
   /** Number of documents grouped into the topN groups */
-  public final int totalGroupedHitCount;
+  public final long totalGroupedHitCount;
 
   /** The total number of unique groups. If <code>null</code> this value is not computed. */
-  public final Integer totalGroupCount;
+  public final Long totalGroupCount;
 
   /** Group results in groupSort order */
   public final GroupDocs<T>[] groups;
@@ -50,7 +50,7 @@ public class TopGroups<T> {
    *  <code>Float.NaN</code> if scores were not computed. */
   public final float maxScore;
 
-  public TopGroups(SortField[] groupSort, SortField[] withinGroupSort, int totalHitCount, int totalGroupedHitCount, GroupDocs<T>[] groups, float maxScore) {
+  public TopGroups(SortField[] groupSort, SortField[] withinGroupSort, long totalHitCount, long totalGroupedHitCount, GroupDocs<T>[] groups, float maxScore) {
     this.groupSort = groupSort;
     this.withinGroupSort = withinGroupSort;
     this.totalHitCount = totalHitCount;
@@ -60,7 +60,7 @@ public class TopGroups<T> {
     this.maxScore = maxScore;
   }
 
-  public TopGroups(TopGroups<T> oldTopGroups, Integer totalGroupCount) {
+  public TopGroups(TopGroups<T> oldTopGroups, Long totalGroupCount) {
     this.groupSort = oldTopGroups.groupSort;
     this.withinGroupSort = oldTopGroups.withinGroupSort;
     this.totalHitCount = oldTopGroups.totalHitCount;
@@ -118,10 +118,10 @@ public class TopGroups<T> {
       return null;
     }
 
-    int totalHitCount = 0;
-    int totalGroupedHitCount = 0;
+    long totalHitCount = 0;
+    long totalGroupedHitCount = 0;
     // Optionally merge the totalGroupCount.
-    Integer totalGroupCount = null;
+    Long totalGroupCount = null;
 
     final int numGroups = shardGroups[0].groups.length;
     for(TopGroups<T> shard : shardGroups) {
@@ -132,7 +132,7 @@ public class TopGroups<T> {
       totalGroupedHitCount += shard.totalGroupedHitCount;
       if (shard.totalGroupCount != null) {
         if (totalGroupCount == null) {
-          totalGroupCount = 0;
+          totalGroupCount = 0L;
         }
 
         totalGroupCount += shard.totalGroupCount;
@@ -154,7 +154,7 @@ public class TopGroups<T> {
       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.NaN;
-      int totalHits = 0;
+      long totalHits = 0;
       double scoreSum = 0.0;
       for(int shardIDX=0;shardIDX<shardGroups.length;shardIDX++) {
         //System.out.println("    shard=" + shardIDX);
diff --git a/lucene/grouping/src/test/org/apache/lucene/search/grouping/TestGrouping.java b/lucene/grouping/src/test/org/apache/lucene/search/grouping/TestGrouping.java
index f1ce508..73832c1 100644
--- a/lucene/grouping/src/test/org/apache/lucene/search/grouping/TestGrouping.java
+++ b/lucene/grouping/src/test/org/apache/lucene/search/grouping/TestGrouping.java
@@ -452,7 +452,7 @@ public class TestGrouping extends LuceneTestCase {
     final List<BytesRef> sortedGroups = new ArrayList<>();
     final List<Comparable<?>[]> sortedGroupFields = new ArrayList<>();
 
-    int totalHitCount = 0;
+    long totalHitCount = 0;
     Set<BytesRef> knownGroups = new HashSet<>();
 
     //System.out.println("TEST: slowGrouping");
@@ -492,7 +492,7 @@ public class TestGrouping extends LuceneTestCase {
     final Comparator<GroupDoc> docSortComp = getComparator(docSort);
     @SuppressWarnings({"unchecked","rawtypes"})
     final GroupDocs<BytesRef>[] result = new GroupDocs[limit-groupOffset];
-    int totalGroupedHitCount = 0;
+    long totalGroupedHitCount = 0;
     for(int idx=groupOffset;idx < limit;idx++) {
       final BytesRef group = sortedGroups.get(idx);
       final List<GroupDoc> docs = groups.get(group);
@@ -523,7 +523,7 @@ public class TestGrouping extends LuceneTestCase {
     if (doAllGroups) {
       return new TopGroups<>(
         new TopGroups<>(groupSort.getSort(), docSort.getSort(), totalHitCount, totalGroupedHitCount, result, Float.NaN),
-          knownGroups.size()
+          (long) knownGroups.size()
       );
     } else {
       return new TopGroups<>(groupSort.getSort(), docSort.getSort(), totalHitCount, totalGroupedHitCount, result, Float.NaN);
@@ -960,7 +960,7 @@ public class TestGrouping extends LuceneTestCase {
           
           if (doAllGroups) {
             TopGroups<BytesRef> tempTopGroups = getTopGroups(c2, docOffset);
-            groupsResult = new TopGroups<>(tempTopGroups, allGroupsCollector.getGroupCount());
+            groupsResult = new TopGroups<>(tempTopGroups, (long) allGroupsCollector.getGroupCount());
           } else {
             groupsResult = getTopGroups(c2, docOffset);
           }
@@ -1046,8 +1046,8 @@ public class TestGrouping extends LuceneTestCase {
         final TopGroups<BytesRef> tempTopGroupsBlocks = (TopGroups<BytesRef>) c3.getTopGroups(docSort, groupOffset, docOffset, docOffset+docsPerGroup);
         final TopGroups<BytesRef> groupsResultBlocks;
         if (doAllGroups && tempTopGroupsBlocks != null) {
-          assertEquals((int) tempTopGroupsBlocks.totalGroupCount, allGroupsCollector2.getGroupCount());
-          groupsResultBlocks = new TopGroups<>(tempTopGroupsBlocks, allGroupsCollector2.getGroupCount());
+          assertEquals((long) tempTopGroupsBlocks.totalGroupCount, (long) allGroupsCollector2.getGroupCount());
+          groupsResultBlocks = new TopGroups<>(tempTopGroupsBlocks, (long) allGroupsCollector2.getGroupCount());
         } else {
           groupsResultBlocks = tempTopGroupsBlocks;
         }
diff --git a/solr/core/src/java/org/apache/solr/core/SolrCore.java b/solr/core/src/java/org/apache/solr/core/SolrCore.java
index 5cd3619..30bdba1 100644
--- a/solr/core/src/java/org/apache/solr/core/SolrCore.java
+++ b/solr/core/src/java/org/apache/solr/core/SolrCore.java
@@ -2561,6 +2561,9 @@ public final class SolrCore implements SolrInfoBean, SolrMetricProducer, Closeab
 
     preDecorateResponse(req, rsp);
 
+    if (req.getOriginalParams().get("group") != null) {
+      System.out.println("hello: "+req);
+    }
     /*
      * Keeping this usage of isDebugEnabled because the extraction of the log data as a string might be slow. TODO:
      * Determine how likely it is that something is going to go wrong that will prevent the logging at INFO further
diff --git a/solr/core/src/java/org/apache/solr/handler/component/ResponseBuilder.java b/solr/core/src/java/org/apache/solr/handler/component/ResponseBuilder.java
index 40af722..7eb0700 100644
--- a/solr/core/src/java/org/apache/solr/handler/component/ResponseBuilder.java
+++ b/solr/core/src/java/org/apache/solr/handler/component/ResponseBuilder.java
@@ -185,12 +185,12 @@ public class ResponseBuilder
 
   // Context fields for grouping
   public final Map<String, Collection<SearchGroup<BytesRef>>> mergedSearchGroups = new HashMap<>();
-  public final Map<String, Integer> mergedGroupCounts = new HashMap<>();
+  public final Map<String, Long> mergedGroupCounts = new HashMap<>();
   public final Map<String, Map<SearchGroup<BytesRef>, Set<String>>> searchGroupToShards = new HashMap<>();
   public final Map<String, TopGroups<BytesRef>> mergedTopGroups = new HashMap<>();
   public final Map<String, QueryCommandResult> mergedQueryCommandResults = new HashMap<>();
   public final Map<Object, SolrDocument> retrievedDocuments = new HashMap<>();
-  public int totalHitCount; // Hit count used when distributed grouping is performed.
+  public long totalHitCount; // Hit count used when distributed grouping is performed.
   // Used for timeAllowed parameter. First phase elapsed time is subtracted from the time allowed for the second phase.
   public int firstPhaseElapsedTime;
 
diff --git a/solr/core/src/java/org/apache/solr/request/SimpleFacets.java b/solr/core/src/java/org/apache/solr/request/SimpleFacets.java
index b1acea0..f245ce6 100644
--- a/solr/core/src/java/org/apache/solr/request/SimpleFacets.java
+++ b/solr/core/src/java/org/apache/solr/request/SimpleFacets.java
@@ -343,7 +343,7 @@ public class SimpleFacets {
         .add(mainQueryFilter, Occur.FILTER)
         .build();
     searcher.search(filteredFacetQuery, collector);
-    return collector.getGroupCount();
+    return (int) collector.getGroupCount(); // nocommit, do we need to tackle this as a long?
   }
 
   enum FacetMethod {
diff --git a/solr/core/src/java/org/apache/solr/search/Grouping.java b/solr/core/src/java/org/apache/solr/search/Grouping.java
index 55e511c..e40b152 100644
--- a/solr/core/src/java/org/apache/solr/search/Grouping.java
+++ b/solr/core/src/java/org/apache/solr/search/Grouping.java
@@ -105,7 +105,7 @@ public class Grouping {
   private Filter luceneFilter;
   private NamedList grouped = new SimpleOrderedMap();
   private Set<Integer> idSet = new LinkedHashSet<>();  // used for tracking unique docs when we need a doclist
-  private int maxMatches;  // max number of matches from any grouping command
+  private long maxMatches;  // max number of matches from any grouping command
   private float maxScore = Float.NaN;  // max score seen in any doclist
   private boolean signalCacheWarning = false;
   private TimeLimitingCollector timeLimitingCollector;
@@ -573,7 +573,7 @@ public class Grouping {
      *
      * @return the number of matches for this <code>Command</code>
      */
-    public abstract int getMatches();
+    public abstract long getMatches();
 
     /**
      * Returns the number of groups found for this <code>Command</code>.
@@ -581,7 +581,7 @@ public class Grouping {
      *
      * @return the number of groups found for this <code>Command</code>
      */
-    protected Integer getNumberOfGroups() {
+    protected Long getNumberOfGroups() {
       return null;
     }
 
@@ -597,11 +597,11 @@ public class Grouping {
       NamedList groupResult = new SimpleOrderedMap();
       grouped.add(key, groupResult);  // grouped={ key={
 
-      int matches = getMatches();
+      long matches = getMatches();
       groupResult.add("matches", matches);
       if (totalCount == TotalCount.grouped) {
-        Integer totalNrOfGroups = getNumberOfGroups();
-        groupResult.add("ngroups", totalNrOfGroups == null ? Integer.valueOf(0) : totalNrOfGroups);
+        Long totalNrOfGroups = getNumberOfGroups();
+        groupResult.add("ngroups", totalNrOfGroups == null ? Long.valueOf(0) : totalNrOfGroups);
       }
       maxMatches = Math.max(maxMatches, matches);
       return groupResult;
@@ -827,7 +827,7 @@ public class Grouping {
     }
 
     @Override
-    public int getMatches() {
+    public long getMatches() {
       if (result == null && fallBackCollector == null) {
         return 0;
       }
@@ -836,8 +836,8 @@ public class Grouping {
     }
 
     @Override
-    protected Integer getNumberOfGroups() {
-      return allGroupsCollector == null ? null : allGroupsCollector.getGroupCount();
+    protected Long getNumberOfGroups() {
+      return allGroupsCollector == null ? null : (long) allGroupsCollector.getGroupCount();
     }
   }
 
@@ -901,7 +901,7 @@ public class Grouping {
     }
 
     @Override
-    public int getMatches() {
+    public long getMatches() {
       return collector.getMatches();
     }
   }
@@ -1022,7 +1022,7 @@ public class Grouping {
     }
 
     @Override
-    public int getMatches() {
+    public long getMatches() {
       if (result == null && fallBackCollector == null) {
         return 0;
       }
@@ -1031,8 +1031,8 @@ public class Grouping {
     }
 
     @Override
-    protected Integer getNumberOfGroups() {
-      return allGroupsCollector == null ? null : allGroupsCollector.getGroupCount();
+    protected Long getNumberOfGroups() {
+      return allGroupsCollector == null ? null : (long) allGroupsCollector.getGroupCount();
     }
 
   }
diff --git a/solr/core/src/java/org/apache/solr/search/grouping/CommandHandler.java b/solr/core/src/java/org/apache/solr/search/grouping/CommandHandler.java
index 8fe1a6b..c8516a6 100644
--- a/solr/core/src/java/org/apache/solr/search/grouping/CommandHandler.java
+++ b/solr/core/src/java/org/apache/solr/search/grouping/CommandHandler.java
@@ -122,7 +122,7 @@ public class CommandHandler {
   private final boolean truncateGroups;
   private final boolean includeHitCount;
   private boolean partialResults = false;
-  private int totalHitCount;
+  private long totalHitCount;
 
   private DocSet docSet;
 
@@ -245,7 +245,7 @@ public class CommandHandler {
     }
   }
 
-  public int getTotalHitCount() {
+  public long getTotalHitCount() {
     return totalHitCount;
   }
 }
diff --git a/solr/core/src/java/org/apache/solr/search/grouping/distributed/command/QueryCommandResult.java b/solr/core/src/java/org/apache/solr/search/grouping/distributed/command/QueryCommandResult.java
index 391ecfa..5cf0d3a 100644
--- a/solr/core/src/java/org/apache/solr/search/grouping/distributed/command/QueryCommandResult.java
+++ b/solr/core/src/java/org/apache/solr/search/grouping/distributed/command/QueryCommandResult.java
@@ -24,10 +24,10 @@ import org.apache.lucene.search.TopDocs;
 public class QueryCommandResult {
 
   private final TopDocs topDocs;
-  private final int matches;
+  private final long matches;
   private final float maxScore;
 
-  public QueryCommandResult(TopDocs topDocs, int matches, float maxScore) {
+  public QueryCommandResult(TopDocs topDocs, long matches, float maxScore) {
     this.topDocs = topDocs;
     this.matches = matches;
     this.maxScore = maxScore;
@@ -37,7 +37,7 @@ public class QueryCommandResult {
     return topDocs;
   }
 
-  public int getMatches() {
+  public long getMatches() {
     return matches;
   }
 
diff --git a/solr/core/src/java/org/apache/solr/search/grouping/distributed/command/SearchGroupsFieldCommand.java b/solr/core/src/java/org/apache/solr/search/grouping/distributed/command/SearchGroupsFieldCommand.java
index 425a987..1d2e0c6 100644
--- a/solr/core/src/java/org/apache/solr/search/grouping/distributed/command/SearchGroupsFieldCommand.java
+++ b/solr/core/src/java/org/apache/solr/search/grouping/distributed/command/SearchGroupsFieldCommand.java
@@ -132,9 +132,9 @@ public class SearchGroupsFieldCommand implements Command<SearchGroupsFieldComman
     } else {
       topGroups = Collections.emptyList();
     }
-    final Integer groupCount;
+    final Long groupCount;
     if (allGroupsCollector != null) {
-      groupCount = allGroupsCollector.getGroupCount();
+      groupCount = (long) allGroupsCollector.getGroupCount();
     } else {
       groupCount = null;
     }
diff --git a/solr/core/src/java/org/apache/solr/search/grouping/distributed/command/SearchGroupsFieldCommandResult.java b/solr/core/src/java/org/apache/solr/search/grouping/distributed/command/SearchGroupsFieldCommandResult.java
index 8860383..5aa8676 100644
--- a/solr/core/src/java/org/apache/solr/search/grouping/distributed/command/SearchGroupsFieldCommandResult.java
+++ b/solr/core/src/java/org/apache/solr/search/grouping/distributed/command/SearchGroupsFieldCommandResult.java
@@ -26,15 +26,15 @@ import org.apache.lucene.util.BytesRef;
  */
 public class SearchGroupsFieldCommandResult {
 
-  private final Integer groupCount;
+  private final Long groupCount;
   private final Collection<SearchGroup<BytesRef>> searchGroups;
 
-  public SearchGroupsFieldCommandResult(Integer groupCount, Collection<SearchGroup<BytesRef>> searchGroups) {
+  public SearchGroupsFieldCommandResult(Long groupCount, Collection<SearchGroup<BytesRef>> searchGroups) {
     this.groupCount = groupCount;
     this.searchGroups = searchGroups;
   }
 
-  public Integer getGroupCount() {
+  public Long getGroupCount() {
     return groupCount;
   }
 
diff --git a/solr/core/src/java/org/apache/solr/search/grouping/distributed/responseprocessor/SearchGroupShardResponseProcessor.java b/solr/core/src/java/org/apache/solr/search/grouping/distributed/responseprocessor/SearchGroupShardResponseProcessor.java
index 016da1d..42dc662 100644
--- a/solr/core/src/java/org/apache/solr/search/grouping/distributed/responseprocessor/SearchGroupShardResponseProcessor.java
+++ b/solr/core/src/java/org/apache/solr/search/grouping/distributed/responseprocessor/SearchGroupShardResponseProcessor.java
@@ -67,7 +67,7 @@ public class SearchGroupShardResponseProcessor implements ShardResponseProcessor
 
     SearchGroupsResultTransformer serializer = new SearchGroupsResultTransformer(rb.req.getSearcher());
     int maxElapsedTime = 0;
-    int hitCountDuringFirstPhase = 0;
+    long hitCountDuringFirstPhase = 0;
 
     NamedList<Object> shardInfo = null;
     if (rb.req.getParams().getBool(ShardParams.SHARDS_INFO, false)) {
@@ -89,7 +89,7 @@ public class SearchGroupShardResponseProcessor implements ShardResponseProcessor
           t.printStackTrace(new PrintWriter(trace));
           nl.add("trace", trace.toString());
         } else {
-          nl.add("numFound", (Integer) srsp.getSolrResponse().getResponse().get("totalHitCount"));
+          nl.add("numFound", ((Number) srsp.getSolrResponse().getResponse().get("totalHitCount")).longValue());
         }
         if (srsp.getSolrResponse() != null) {
           nl.add("time", srsp.getSolrResponse().getElapsedTime());
@@ -111,11 +111,11 @@ public class SearchGroupShardResponseProcessor implements ShardResponseProcessor
         String field = entry.getKey();
         final SearchGroupsFieldCommandResult firstPhaseCommandResult = result.get(field);
 
-        final Integer groupCount = firstPhaseCommandResult.getGroupCount();
+        final Long groupCount = firstPhaseCommandResult.getGroupCount();
         if (groupCount != null) {
-          Integer existingGroupCount = rb.mergedGroupCounts.get(field);
+          Long existingGroupCount = rb.mergedGroupCounts.get(field);
           // Assuming groups don't cross shard boundary...
-          rb.mergedGroupCounts.put(field, existingGroupCount != null ? Integer.valueOf(existingGroupCount + groupCount) : groupCount);
+          rb.mergedGroupCounts.put(field, existingGroupCount != null ? Long.valueOf(existingGroupCount + groupCount) : groupCount);
         }
 
         final Collection<SearchGroup<BytesRef>> searchGroups = firstPhaseCommandResult.getSearchGroups();
@@ -134,7 +134,7 @@ public class SearchGroupShardResponseProcessor implements ShardResponseProcessor
           shards.add(srsp.getShard());
         }
       }
-      hitCountDuringFirstPhase += (Integer) srsp.getSolrResponse().getResponse().get("totalHitCount");
+      hitCountDuringFirstPhase += ((Number) srsp.getSolrResponse().getResponse().get("totalHitCount")).longValue();
     }
     rb.totalHitCount = hitCountDuringFirstPhase;
     rb.firstPhaseElapsedTime = maxElapsedTime;
diff --git a/solr/core/src/java/org/apache/solr/search/grouping/distributed/shardresultserializer/SearchGroupsResultTransformer.java b/solr/core/src/java/org/apache/solr/search/grouping/distributed/shardresultserializer/SearchGroupsResultTransformer.java
index 425ca5b..6ca58ce 100644
--- a/solr/core/src/java/org/apache/solr/search/grouping/distributed/shardresultserializer/SearchGroupsResultTransformer.java
+++ b/solr/core/src/java/org/apache/solr/search/grouping/distributed/shardresultserializer/SearchGroupsResultTransformer.java
@@ -58,7 +58,7 @@ public class SearchGroupsResultTransformer implements ShardResultTransformer<Lis
         if (searchGroups != null) {
           commandResult.add(TOP_GROUPS, serializeSearchGroup(searchGroups, fieldCommand));
         }
-        final Integer groupedCount = fieldCommandResult.getGroupCount();
+        final Long groupedCount = fieldCommandResult.getGroupCount();
         if (groupedCount != null) {
           commandResult.add(GROUP_COUNT, groupedCount);
         }
@@ -111,7 +111,7 @@ public class SearchGroupsResultTransformer implements ShardResultTransformer<Lis
         }
       }
 
-      final Integer groupCount = (Integer) topGroupsAndGroupCount.get(GROUP_COUNT);
+      final Long groupCount = (Long) topGroupsAndGroupCount.get(GROUP_COUNT);
       result.put(command.getKey(), new SearchGroupsFieldCommandResult(groupCount, searchGroups));
     }
     return result;
diff --git a/solr/core/src/java/org/apache/solr/search/grouping/distributed/shardresultserializer/TopGroupsResultTransformer.java b/solr/core/src/java/org/apache/solr/search/grouping/distributed/shardresultserializer/TopGroupsResultTransformer.java
index fb5bd32..13eef04 100644
--- a/solr/core/src/java/org/apache/solr/search/grouping/distributed/shardresultserializer/TopGroupsResultTransformer.java
+++ b/solr/core/src/java/org/apache/solr/search/grouping/distributed/shardresultserializer/TopGroupsResultTransformer.java
@@ -95,10 +95,10 @@ public class TopGroupsResultTransformer implements ShardResultTransformer<List<C
     for (Map.Entry<String, NamedList> entry : shardResponse) {
       String key = entry.getKey();
       NamedList commandResult = entry.getValue();
-      Integer totalGroupedHitCount = (Integer) commandResult.get("totalGroupedHitCount");
+      Long totalGroupedHitCount = (Long) commandResult.get("totalGroupedHitCount");
       Number totalHits = (Number) commandResult.get("totalHits"); // previously Integer now Long
       if (totalHits != null) {
-        Integer matches = (Integer) commandResult.get("matches");
+        Long matches = (Long) commandResult.get("matches");
         Float maxScore = (Float) commandResult.get("maxScore");
         if (maxScore == null) {
           maxScore = Float.NaN;
@@ -117,7 +117,7 @@ public class TopGroupsResultTransformer implements ShardResultTransformer<List<C
         continue;
       }
 
-      Integer totalHitCount = (Integer) commandResult.get("totalHitCount");
+      Long totalHitCount = ((Number) commandResult.get("totalHitCount")).longValue();
 
       List<GroupDocs<BytesRef>> groupDocs = new ArrayList<>();
       for (int i = 2; i < commandResult.size(); i++) {
diff --git a/solr/core/src/java/org/apache/solr/search/grouping/endresulttransformer/GroupedEndResultTransformer.java b/solr/core/src/java/org/apache/solr/search/grouping/endresulttransformer/GroupedEndResultTransformer.java
index 3ba3470..9f26b8f 100644
--- a/solr/core/src/java/org/apache/solr/search/grouping/endresulttransformer/GroupedEndResultTransformer.java
+++ b/solr/core/src/java/org/apache/solr/search/grouping/endresulttransformer/GroupedEndResultTransformer.java
@@ -63,7 +63,7 @@ public class GroupedEndResultTransformer implements EndResultTransformer {
         TopGroups<BytesRef> topGroups = (TopGroups<BytesRef>) value;
         NamedList<Object> command = new SimpleOrderedMap<>();
         command.add("matches", rb.totalHitCount);
-        Integer totalGroupCount = rb.mergedGroupCounts.get(entry.getKey());
+        Long totalGroupCount = rb.mergedGroupCounts.get(entry.getKey());
         if (totalGroupCount != null) {
           command.add("ngroups", totalGroupCount);
         }
diff --git a/solr/core/src/test/org/apache/solr/TestDistributedGrouping.java b/solr/core/src/test/org/apache/solr/TestDistributedGrouping.java
index 7b759d0..a875f27 100644
--- a/solr/core/src/test/org/apache/solr/TestDistributedGrouping.java
+++ b/solr/core/src/test/org/apache/solr/TestDistributedGrouping.java
@@ -311,8 +311,8 @@ public class TestDistributedGrouping extends BaseDistributedSearchTestCase {
     QueryResponse rsp = client.query(params);
     NamedList nl = (NamedList<?>) rsp.getResponse().get("grouped");
     nl = (NamedList<?>) nl.getVal(0);
-    int matches = (Integer) nl.getVal(0);
-    int groupCount = (Integer) nl.get("ngroups");
+    long matches = (Long) nl.getVal(0);
+    long groupCount = (Long) nl.get("ngroups");
     assertEquals(100 * shardsArr.length, matches);
     assertEquals(shardsArr.length, groupCount);
 
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/response/GroupCommand.java b/solr/solrj/src/java/org/apache/solr/client/solrj/response/GroupCommand.java
index fd2bdb7..c38fd6f 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/response/GroupCommand.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/response/GroupCommand.java
@@ -45,8 +45,8 @@ public class GroupCommand implements Serializable {
 
   private final String _name;
   private final List<Group> _values = new ArrayList<>();
-  private final int _matches;
-  private final Integer _ngroups;
+  private final long _matches;
+  private final Long _ngroups; // nocommit needs to be long too
 
   /**
    * Creates a GroupCommand instance
@@ -54,7 +54,7 @@ public class GroupCommand implements Serializable {
    * @param name    The name of this command
    * @param matches The total number of documents found for this command
    */
-  public GroupCommand(String name, int matches) {
+  public GroupCommand(String name, long matches) {
     _name = name;
     _matches = matches;
     _ngroups = null;
@@ -67,7 +67,7 @@ public class GroupCommand implements Serializable {
    * @param matches The total number of documents found for this command
    * @param nGroups The total number of groups found for this command.
    */
-  public GroupCommand(String name, int matches, int nGroups) {
+  public GroupCommand(String name, long matches, long nGroups) {
     _name = name;
     _matches = matches;
     _ngroups = nGroups;
@@ -106,7 +106,7 @@ public class GroupCommand implements Serializable {
    *
    * @return the total number of documents found for this command.
    */
-  public int getMatches() {
+  public long getMatches() {
     return _matches;
   }
 
@@ -117,7 +117,7 @@ public class GroupCommand implements Serializable {
    *
    * @return the total number of groups found for this command.
    */
-  public Integer getNGroups() {
+  public Long getNGroups() {
     return _ngroups;
   }
 
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/response/QueryResponse.java b/solr/solrj/src/java/org/apache/solr/client/solrj/response/QueryResponse.java
index 92db560..5f60b4f 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/response/QueryResponse.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/response/QueryResponse.java
@@ -266,11 +266,11 @@ public class QueryResponse extends SolrResponseBase
         }
 
         if (oGroups != null) {
-          Integer iMatches = (Integer) oMatches;
+          Long iMatches = (Long) oMatches;
           ArrayList<Object> groupsArr = (ArrayList<Object>) oGroups;
           GroupCommand groupedCommand;
           if (oNGroups != null) {
-            Integer iNGroups = (Integer) oNGroups;
+            Long iNGroups = (Long) oNGroups;
             groupedCommand = new GroupCommand(fieldName, iMatches, iNGroups);
           } else {
             groupedCommand = new GroupCommand(fieldName, iMatches);
@@ -289,7 +289,7 @@ public class QueryResponse extends SolrResponseBase
           Integer iMatches = (Integer) oMatches;
           GroupCommand groupCommand;
           if (oNGroups != null) {
-            Integer iNGroups = (Integer) oNGroups;
+            Long iNGroups = (Long) oNGroups;
             groupCommand = new GroupCommand(fieldName, iMatches, iNGroups);
           } else {
             groupCommand = new GroupCommand(fieldName, iMatches);
diff --git a/solr/solrj/src/test-files/solrj/sampleGroupResponse.xml b/solr/solrj/src/test-files/solrj/sampleGroupResponse.xml
index 26fcdfa..6f71152 100644
--- a/solr/solrj/src/test-files/solrj/sampleGroupResponse.xml
+++ b/solr/solrj/src/test-files/solrj/sampleGroupResponse.xml
@@ -13,8 +13,8 @@
   </lst>
   <lst name="grouped">
     <lst name="acco_id">
-      <int name="matches">30000000</int>
-      <int name="ngroups">5687</int>
+      <long name="matches">30000000</long>
+      <long name="ngroups">5687</long>
       <arr name="groups">
         <lst>
           <str name="groupValue">116_ar</str>