You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by mu...@apache.org on 2020/04/10 14:01:15 UTC

[lucene-solr] branch master updated: SOLR-11775: return long val for facet count in json facet

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

munendrasn pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/lucene-solr.git


The following commit(s) were added to refs/heads/master by this push:
     new 36b280b  SOLR-11775: return long val for facet count in json facet
36b280b is described below

commit 36b280bd0a21952ea54c7567f037eb48dc93205a
Author: Munendra S N <mu...@apache.org>
AuthorDate: Fri Apr 10 19:16:54 2020 +0530

    SOLR-11775: return long val for facet count in json facet
    
    * Long value is returned for any count related to json facets
      irrespective of number of shards
---
 .../java/org/apache/solr/request/SimpleFacets.java |  4 +-
 .../apache/solr/search/facet/AggValueSource.java   |  2 +-
 .../java/org/apache/solr/search/facet/AvgAgg.java  |  2 +-
 .../org/apache/solr/search/facet/CountAgg.java     |  2 +-
 .../org/apache/solr/search/facet/CountValsAgg.java |  2 +-
 .../solr/search/facet/FacetFieldProcessor.java     | 16 ++--
 .../search/facet/FacetFieldProcessorByHashDV.java  | 24 +++---
 .../apache/solr/search/facet/FacetProcessor.java   | 14 ++--
 .../org/apache/solr/search/facet/FacetRange.java   |  2 +-
 .../java/org/apache/solr/search/facet/HLLAgg.java  |  2 +-
 .../org/apache/solr/search/facet/MinMaxAgg.java    |  2 +-
 .../org/apache/solr/search/facet/MissingAgg.java   |  2 +-
 .../apache/solr/search/facet/PercentileAgg.java    |  2 +-
 .../apache/solr/search/facet/RelatednessAgg.java   |  2 +-
 .../java/org/apache/solr/search/facet/SlotAcc.java | 19 +++--
 .../org/apache/solr/search/facet/StddevAgg.java    |  2 +-
 .../java/org/apache/solr/search/facet/SumAgg.java  |  2 +-
 .../org/apache/solr/search/facet/SumsqAgg.java     |  2 +-
 .../apache/solr/search/facet/UnInvertedField.java  |  2 +-
 .../org/apache/solr/search/facet/UniqueAgg.java    |  2 +-
 .../apache/solr/search/facet/UniqueBlockAgg.java   |  2 +-
 .../solr/search/facet/UniqueBlockFieldAgg.java     |  2 +-
 .../solr/search/facet/UniqueBlockQueryAgg.java     |  2 +-
 .../org/apache/solr/search/facet/VarianceAgg.java  |  2 +-
 .../apache/solr/schema/CurrencyFieldTypeTest.java  | 94 +++++++++++-----------
 .../apache/solr/schema/TestSortableTextField.java  |  6 +-
 .../solr/search/CurrencyRangeFacetCloudTest.java   | 64 +++++++--------
 .../org/apache/solr/search/facet/DebugAgg.java     | 10 +--
 ...stributedFacetSimpleRefinementLongTailTest.java | 14 ++--
 .../solr/search/facet/RangeFacetCloudTest.java     | 14 +---
 .../apache/solr/search/facet/TestJsonFacets.java   | 58 +++++++++++++
 .../solr/search/facet/TestJsonRangeFacets.java     | 38 +++++++++
 .../src/major-changes-in-solr-9.adoc               |  2 +
 .../src/java/org/apache/solr/SolrTestCaseHS.java   | 45 +++++++++++
 34 files changed, 293 insertions(+), 167 deletions(-)

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 1fc1583..aab7684 100644
--- a/solr/core/src/java/org/apache/solr/request/SimpleFacets.java
+++ b/solr/core/src/java/org/apache/solr/request/SimpleFacets.java
@@ -579,11 +579,11 @@ public class SimpleFacets {
 
               List<NamedList<Object>> buckets = (List<NamedList<Object>>)res.get("buckets");
               for(NamedList<Object> b : buckets) {
-                counts.add(b.get("val").toString(), (Integer)b.get("count"));
+                counts.add(b.get("val").toString(), ((Number)b.get("count")).intValue());
               }
               if(missing) {
                 NamedList<Object> missingCounts = (NamedList<Object>) res.get("missing");
-                counts.add(null, (Integer)missingCounts.get("count"));
+                counts.add(null, ((Number)missingCounts.get("count")).intValue());
               }
             }
           break;
diff --git a/solr/core/src/java/org/apache/solr/search/facet/AggValueSource.java b/solr/core/src/java/org/apache/solr/search/facet/AggValueSource.java
index 6457467..1678c6f 100644
--- a/solr/core/src/java/org/apache/solr/search/facet/AggValueSource.java
+++ b/solr/core/src/java/org/apache/solr/search/facet/AggValueSource.java
@@ -50,7 +50,7 @@ public abstract class AggValueSource extends ValueSource {
   }
 
   // TODO: make abstract
-  public SlotAcc createSlotAcc(FacetContext fcontext, int numDocs, int numSlots) throws IOException {
+  public SlotAcc createSlotAcc(FacetContext fcontext, long numDocs, int numSlots) throws IOException {
     throw new UnsupportedOperationException("NOT IMPLEMENTED " + name + " " + this);
   }
 
diff --git a/solr/core/src/java/org/apache/solr/search/facet/AvgAgg.java b/solr/core/src/java/org/apache/solr/search/facet/AvgAgg.java
index 716bb80..3b6cee0 100644
--- a/solr/core/src/java/org/apache/solr/search/facet/AvgAgg.java
+++ b/solr/core/src/java/org/apache/solr/search/facet/AvgAgg.java
@@ -37,7 +37,7 @@ public class AvgAgg extends SimpleAggValueSource {
   }
 
   @Override
-  public SlotAcc createSlotAcc(FacetContext fcontext, int numDocs, int numSlots) throws IOException {
+  public SlotAcc createSlotAcc(FacetContext fcontext, long numDocs, int numSlots) throws IOException {
     ValueSource vs = getArg();
 
     if (vs instanceof FieldNameValueSource) {
diff --git a/solr/core/src/java/org/apache/solr/search/facet/CountAgg.java b/solr/core/src/java/org/apache/solr/search/facet/CountAgg.java
index fc16917..491622d 100644
--- a/solr/core/src/java/org/apache/solr/search/facet/CountAgg.java
+++ b/solr/core/src/java/org/apache/solr/search/facet/CountAgg.java
@@ -24,7 +24,7 @@ public class CountAgg extends SimpleAggValueSource {
   }
 
   @Override
-  public SlotAcc createSlotAcc(FacetContext fcontext, int numDocs, int numSlots) throws IOException {
+  public SlotAcc createSlotAcc(FacetContext fcontext, long numDocs, int numSlots) throws IOException {
     return new CountSlotArrAcc(fcontext, numSlots);
   }
 
diff --git a/solr/core/src/java/org/apache/solr/search/facet/CountValsAgg.java b/solr/core/src/java/org/apache/solr/search/facet/CountValsAgg.java
index eebe9fc..81fa983 100644
--- a/solr/core/src/java/org/apache/solr/search/facet/CountValsAgg.java
+++ b/solr/core/src/java/org/apache/solr/search/facet/CountValsAgg.java
@@ -37,7 +37,7 @@ public class CountValsAgg extends SimpleAggValueSource {
   }
 
   @Override
-  public SlotAcc createSlotAcc(FacetContext fcontext, int numDocs, int numSlots) throws IOException {
+  public SlotAcc createSlotAcc(FacetContext fcontext, long numDocs, int numSlots) throws IOException {
     ValueSource vs = getArg();
     if (vs instanceof FieldNameValueSource) {
       String field = ((FieldNameValueSource)vs).getFieldName();
diff --git a/solr/core/src/java/org/apache/solr/search/facet/FacetFieldProcessor.java b/solr/core/src/java/org/apache/solr/search/facet/FacetFieldProcessor.java
index 5caea4e..fe418f1 100644
--- a/solr/core/src/java/org/apache/solr/search/facet/FacetFieldProcessor.java
+++ b/solr/core/src/java/org/apache/solr/search/facet/FacetFieldProcessor.java
@@ -108,7 +108,7 @@ abstract class FacetFieldProcessor extends FacetProcessor<FacetField> {
 
   /** This is used to create accs for second phase (or to create accs for all aggs) */
   @Override
-  protected void createAccs(int docCount, int slotCount) throws IOException {
+  protected void createAccs(long docCount, int slotCount) throws IOException {
     if (accMap == null) {
       accMap = new LinkedHashMap<>();
     }
@@ -295,7 +295,7 @@ abstract class FacetFieldProcessor extends FacetProcessor<FacetField> {
                                         IntFunction<Comparable> bucketValFromSlotNumFunc,
                                         Function<Comparable, String> fieldQueryValFunc) throws IOException {
     assert this.sortAcc != null;
-    int numBuckets = 0;
+    long numBuckets = 0;
 
     final int off = fcontext.isShard() ? 0 : (int) freq.offset;
 
@@ -347,7 +347,7 @@ abstract class FacetFieldProcessor extends FacetProcessor<FacetField> {
 
       // screen out buckets not matching mincount
       if (effectiveMincount > 0) {
-        int count = countAcc.getCount(slotNum);
+        long count = countAcc.getCount(slotNum);
         if (count  < effectiveMincount) {
           if (count > 0)
             numBuckets++;  // Still increment numBuckets as long as we have some count.  This is for consistency between distrib and non-distrib mode.
@@ -387,7 +387,7 @@ abstract class FacetFieldProcessor extends FacetProcessor<FacetField> {
     }
 
     FacetDebugInfo fdebug = fcontext.getDebugInfo();
-    if (fdebug != null) fdebug.putInfoItem("numBuckets", (long) numBuckets);
+    if (fdebug != null) fdebug.putInfoItem("numBuckets", numBuckets);
 
     if (freq.allBuckets) {
       SimpleOrderedMap<Object> allBuckets = new SimpleOrderedMap<>();
@@ -507,7 +507,7 @@ abstract class FacetFieldProcessor extends FacetProcessor<FacetField> {
   /** Helper method used solely when looping over buckets to be returned in findTopSlots */
   private void fillBucketFromSlot(SimpleOrderedMap<Object> target, Slot slot,
                                   SlotAcc resortAcc) throws IOException {
-    final int count = countAcc.getCount(slot.slot);
+    final long count = countAcc.getCount(slot.slot);
     target.add("count", count);
     if (count <= 0 && !freq.processEmpty) return;
 
@@ -645,14 +645,14 @@ abstract class FacetFieldProcessor extends FacetProcessor<FacetField> {
   }
   
   @Override
-  protected void processStats(SimpleOrderedMap<Object> bucket, Query bucketQ, DocSet docs, int docCount) throws IOException {
+  protected void processStats(SimpleOrderedMap<Object> bucket, Query bucketQ, DocSet docs, long docCount) throws IOException {
     if (docCount == 0 && !freq.processEmpty || freq.getFacetStats().size() == 0) {
       bucket.add("count", docCount);
       return;
     }
     createAccs(docCount, 1);
     assert null != bucketQ;
-    int collected = collect(docs, 0, slotNum -> { return new SlotContext(bucketQ); });
+    long collected = collect(docs, 0, slotNum -> { return new SlotContext(bucketQ); });
 
     // countAcc.incrementCount(0, collected);  // should we set the counton the acc instead of just passing it?
 
@@ -661,7 +661,7 @@ abstract class FacetFieldProcessor extends FacetProcessor<FacetField> {
   }
 
   // overrides but with different signature!
-  private void addStats(SimpleOrderedMap<Object> target, int count, int slotNum) throws IOException {
+  private void addStats(SimpleOrderedMap<Object> target, long count, int slotNum) throws IOException {
     target.add("count", count);
     if (count > 0 || freq.processEmpty) {
       for (SlotAcc acc : accs) {
diff --git a/solr/core/src/java/org/apache/solr/search/facet/FacetFieldProcessorByHashDV.java b/solr/core/src/java/org/apache/solr/search/facet/FacetFieldProcessorByHashDV.java
index 42d23ef..966da87 100644
--- a/solr/core/src/java/org/apache/solr/search/facet/FacetFieldProcessorByHashDV.java
+++ b/solr/core/src/java/org/apache/solr/search/facet/FacetFieldProcessorByHashDV.java
@@ -57,8 +57,8 @@ class FacetFieldProcessorByHashDV extends FacetFieldProcessor {
     static final float LOAD_FACTOR = 0.7f;
 
     long[] vals;
-    int[] counts;  // maintain the counts here since we need them to tell if there was actually a value anyway
-    int[] oldToNewMapping;
+    long[] counts;  // maintain the counts here since we need them to tell if there was actually a value anyway
+    long[] oldToNewMapping;
 
     int cardinality;
     int threshold;
@@ -66,7 +66,7 @@ class FacetFieldProcessorByHashDV extends FacetFieldProcessor {
     /** sz must be a power of two */
     LongCounts(int sz) {
       vals = new long[sz];
-      counts = new int[sz];
+      counts = new long[sz];
       threshold = (int) (sz * LOAD_FACTOR);
     }
 
@@ -95,7 +95,7 @@ class FacetFieldProcessorByHashDV extends FacetFieldProcessor {
 
       int h = hash(val);
       for (int slot = h & (vals.length-1);  ;slot = (slot + ((h>>7)|1)) & (vals.length-1)) {
-        int count = counts[slot];
+        long count = counts[slot];
         if (count == 0) {
           counts[slot] = 1;
           vals[slot] = val;
@@ -111,14 +111,14 @@ class FacetFieldProcessorByHashDV extends FacetFieldProcessor {
 
     protected void rehash() {
       long[] oldVals = vals;
-      int[] oldCounts = counts;  // after retrieving the count, this array is reused as a mapping to new array
+      long[] oldCounts = counts;  // after retrieving the count, this array is reused as a mapping to new array
       int newCapacity = vals.length << 1;
       vals = new long[newCapacity];
-      counts = new int[newCapacity];
+      counts = new long[newCapacity];
       threshold = (int) (newCapacity * LOAD_FACTOR);
 
       for (int i=0; i<oldVals.length; i++) {
-        int count = oldCounts[i];
+        long count = oldCounts[i];
         if (count == 0) {
           oldCounts[i] = -1;
           continue;
@@ -287,12 +287,12 @@ class FacetFieldProcessorByHashDV extends FacetFieldProcessor {
 
     countAcc = new CountSlotAcc(fcontext) {
       @Override
-      public void incrementCount(int slot, int count) {
+      public void incrementCount(int slot, long count) {
         throw new UnsupportedOperationException();
       }
 
       @Override
-      public int getCount(int slot) {
+      public long getCount(int slot) {
         return table.counts[slot];
       }
 
@@ -313,7 +313,7 @@ class FacetFieldProcessorByHashDV extends FacetFieldProcessor {
 
       @Override
       public int compare(int slotA, int slotB) {
-        return Integer.compare( table.counts[slotA], table.counts[slotB] );
+        return Long.compare( table.counts[slotA], table.counts[slotB] );
       }
 
       @Override
@@ -455,7 +455,7 @@ class FacetFieldProcessorByHashDV extends FacetFieldProcessor {
     }
 
     final int finalNumSlots = numSlots;
-    final int[] mapping = table.oldToNewMapping;
+    final long[] mapping = table.oldToNewMapping;
 
     SlotAcc.Resizer resizer = new SlotAcc.Resizer() {
       @Override
@@ -466,7 +466,7 @@ class FacetFieldProcessorByHashDV extends FacetFieldProcessor {
       @Override
       public int getNewSlot(int oldSlot) {
         if (oldSlot < mapping.length) {
-          return mapping[oldSlot];
+          return (int) mapping[oldSlot];
         }
         if (oldSlot == oldAllBucketsSlot) {
           return allBucketsSlot;
diff --git a/solr/core/src/java/org/apache/solr/search/facet/FacetProcessor.java b/solr/core/src/java/org/apache/solr/search/facet/FacetProcessor.java
index 8a996b1..b8271f5 100644
--- a/solr/core/src/java/org/apache/solr/search/facet/FacetProcessor.java
+++ b/solr/core/src/java/org/apache/solr/search/facet/FacetProcessor.java
@@ -290,19 +290,19 @@ public abstract class FacetProcessor<FacetRequestT extends FacetRequest>  {
     return appliedFilters;
   }
 
-  protected void processStats(SimpleOrderedMap<Object> bucket, Query bucketQ, DocSet docs, int docCount) throws IOException {
+  protected void processStats(SimpleOrderedMap<Object> bucket, Query bucketQ, DocSet docs, long docCount) throws IOException {
     if (docCount == 0 && !freq.processEmpty || freq.getFacetStats().size() == 0) {
       bucket.add("count", docCount);
       return;
     }
     createAccs(docCount, 1);
-    int collected = collect(docs, 0, slotNum -> { return new SlotContext(bucketQ); });
+    long collected = collect(docs, 0, slotNum -> { return new SlotContext(bucketQ); });
     countAcc.incrementCount(0, collected);
     assert collected == docCount;
     addStats(bucket, 0);
   }
 
-  protected void createAccs(int docCount, int slotCount) throws IOException {
+  protected void createAccs(long docCount, int slotCount) throws IOException {
     accMap = new LinkedHashMap<>();
 
     // allow a custom count acc to be used
@@ -332,8 +332,8 @@ public abstract class FacetProcessor<FacetRequestT extends FacetRequest>  {
     }
   }
 
-  int collect(DocSet docs, int slot, IntFunction<SlotContext> slotContext) throws IOException {
-    int count = 0;
+  long collect(DocSet docs, int slot, IntFunction<SlotContext> slotContext) throws IOException {
+    long count = 0;
     SolrIndexSearcher searcher = fcontext.searcher;
 
     if (0 == docs.size()) {
@@ -392,7 +392,7 @@ public abstract class FacetProcessor<FacetRequestT extends FacetRequest>  {
   }
 
   void addStats(SimpleOrderedMap<Object> target, int slotNum) throws IOException {
-    int count = countAcc.getCount(slotNum);
+    long count = countAcc.getCount(slotNum);
     target.add("count", count);
     if (count > 0 || freq.processEmpty) {
       for (SlotAcc acc : accs) {
@@ -405,7 +405,7 @@ public abstract class FacetProcessor<FacetRequestT extends FacetRequest>  {
 
     boolean needDocSet = (skip==false && freq.getFacetStats().size() > 0) || freq.getSubFacets().size() > 0;
 
-    int count;
+    long count;
 
     if (result != null) {
       count = result.size();
diff --git a/solr/core/src/java/org/apache/solr/search/facet/FacetRange.java b/solr/core/src/java/org/apache/solr/search/facet/FacetRange.java
index a74f35d..a93bc07 100644
--- a/solr/core/src/java/org/apache/solr/search/facet/FacetRange.java
+++ b/solr/core/src/java/org/apache/solr/search/facet/FacetRange.java
@@ -578,7 +578,7 @@ class FacetRangeProcessor extends FacetProcessor<FacetRange> {
     DocSet intersection = fcontext.searcher.getDocSet(rangeQ, fcontext.base);
     filters[slot] = rangeQ;
     intersections[slot] = intersection;  // save for later  // TODO: only save if number of slots is small enough?
-    int num = collect(intersection, slot, slotNum -> { return new SlotContext(rangeQ); });
+    long num = collect(intersection, slot, slotNum -> { return new SlotContext(rangeQ); });
     countAcc.incrementCount(slot, num); // TODO: roll this into collect()
   }
 
diff --git a/solr/core/src/java/org/apache/solr/search/facet/HLLAgg.java b/solr/core/src/java/org/apache/solr/search/facet/HLLAgg.java
index 32c1b14..ff7b2a2 100644
--- a/solr/core/src/java/org/apache/solr/search/facet/HLLAgg.java
+++ b/solr/core/src/java/org/apache/solr/search/facet/HLLAgg.java
@@ -50,7 +50,7 @@ public class HLLAgg extends StrAggValueSource {
   }
 
   @Override
-  public SlotAcc createSlotAcc(FacetContext fcontext, int numDocs, int numSlots) throws IOException {
+  public SlotAcc createSlotAcc(FacetContext fcontext, long numDocs, int numSlots) throws IOException {
     SchemaField sf = fcontext.qcontext.searcher().getSchema().getField(getArg());
     if (sf.multiValued() || sf.getType().multiValuedFieldCache()) {
       if (sf.getType().isPointField()) {
diff --git a/solr/core/src/java/org/apache/solr/search/facet/MinMaxAgg.java b/solr/core/src/java/org/apache/solr/search/facet/MinMaxAgg.java
index f369226..d036ee1 100644
--- a/solr/core/src/java/org/apache/solr/search/facet/MinMaxAgg.java
+++ b/solr/core/src/java/org/apache/solr/search/facet/MinMaxAgg.java
@@ -46,7 +46,7 @@ public class MinMaxAgg extends SimpleAggValueSource {
   }
 
   @Override
-  public SlotAcc createSlotAcc(FacetContext fcontext, int numDocs, int numSlots) throws IOException {
+  public SlotAcc createSlotAcc(FacetContext fcontext, long numDocs, int numSlots) throws IOException {
     ValueSource vs = getArg();
 
     SchemaField sf = null;
diff --git a/solr/core/src/java/org/apache/solr/search/facet/MissingAgg.java b/solr/core/src/java/org/apache/solr/search/facet/MissingAgg.java
index 2bf2513..4ff980f 100644
--- a/solr/core/src/java/org/apache/solr/search/facet/MissingAgg.java
+++ b/solr/core/src/java/org/apache/solr/search/facet/MissingAgg.java
@@ -37,7 +37,7 @@ public class MissingAgg extends SimpleAggValueSource {
   }
 
   @Override
-  public SlotAcc createSlotAcc(FacetContext fcontext, int numDocs, int numSlots) throws IOException {
+  public SlotAcc createSlotAcc(FacetContext fcontext, long numDocs, int numSlots) throws IOException {
     ValueSource vs = getArg();
 
     if (vs instanceof FieldNameValueSource) {
diff --git a/solr/core/src/java/org/apache/solr/search/facet/PercentileAgg.java b/solr/core/src/java/org/apache/solr/search/facet/PercentileAgg.java
index 24e3273..956b179 100644
--- a/solr/core/src/java/org/apache/solr/search/facet/PercentileAgg.java
+++ b/solr/core/src/java/org/apache/solr/search/facet/PercentileAgg.java
@@ -49,7 +49,7 @@ public class PercentileAgg extends SimpleAggValueSource {
   }
 
   @Override
-  public SlotAcc createSlotAcc(FacetContext fcontext, int numDocs, int numSlots) throws IOException {
+  public SlotAcc createSlotAcc(FacetContext fcontext, long numDocs, int numSlots) throws IOException {
     ValueSource vs = getArg();
 
     if (vs instanceof FieldNameValueSource) {
diff --git a/solr/core/src/java/org/apache/solr/search/facet/RelatednessAgg.java b/solr/core/src/java/org/apache/solr/search/facet/RelatednessAgg.java
index 662496f..81d0f3b 100644
--- a/solr/core/src/java/org/apache/solr/search/facet/RelatednessAgg.java
+++ b/solr/core/src/java/org/apache/solr/search/facet/RelatednessAgg.java
@@ -122,7 +122,7 @@ public class RelatednessAgg extends AggValueSource {
   }
 
 
-  public SlotAcc createSlotAcc(FacetContext fcontext, int numDocs, int numSlots) throws IOException {
+  public SlotAcc createSlotAcc(FacetContext fcontext, long numDocs, int numSlots) throws IOException {
     // TODO: Ideally this is where we should check fgQ/bgQ for 'null' and apply defaults...
     //
     // we want to walk up the fcontext and inherit the queries from any ancestor SKGAgg
diff --git a/solr/core/src/java/org/apache/solr/search/facet/SlotAcc.java b/solr/core/src/java/org/apache/solr/search/facet/SlotAcc.java
index 2a92348..99387be 100644
--- a/solr/core/src/java/org/apache/solr/search/facet/SlotAcc.java
+++ b/solr/core/src/java/org/apache/solr/search/facet/SlotAcc.java
@@ -578,17 +578,17 @@ abstract class CountSlotAcc extends SlotAcc {
     super(fcontext);
   }
 
-  public abstract void incrementCount(int slot, int count);
+  public abstract void incrementCount(int slot, long count);
 
-  public abstract int getCount(int slot);
+  public abstract long getCount(int slot);
 }
 
 class CountSlotArrAcc extends CountSlotAcc {
-  int[] result;
+  long[] result;
 
   public CountSlotArrAcc(FacetContext fcontext, int numSlots) {
     super(fcontext);
-    result = new int[numSlots];
+    result = new long[numSlots];
   }
 
   @Override
@@ -600,7 +600,7 @@ class CountSlotArrAcc extends CountSlotAcc {
 
   @Override
   public int compare(int slotA, int slotB) {
-    return Integer.compare(result[slotA], result[slotB]);
+    return Long.compare(result[slotA], result[slotB]);
   }
 
   @Override
@@ -608,16 +608,18 @@ class CountSlotArrAcc extends CountSlotAcc {
     return result[slotNum];
   }
 
-  public void incrementCount(int slot, int count) {
+  @Override
+  public void incrementCount(int slot, long count) {
     result[slot] += count;
   }
 
-  public int getCount(int slot) {
+  @Override
+  public long getCount(int slot) {
     return result[slot];
   }
 
   // internal and expert
-  int[] getCountArray() {
+  long[] getCountArray() {
     return result;
   }
 
@@ -642,6 +644,7 @@ class SortSlotAcc extends SlotAcc {
     // no-op
   }
 
+  @Override
   public int compare(int slotA, int slotB) {
     return slotA - slotB;
   }
diff --git a/solr/core/src/java/org/apache/solr/search/facet/StddevAgg.java b/solr/core/src/java/org/apache/solr/search/facet/StddevAgg.java
index d7237d3..d0fb90b 100644
--- a/solr/core/src/java/org/apache/solr/search/facet/StddevAgg.java
+++ b/solr/core/src/java/org/apache/solr/search/facet/StddevAgg.java
@@ -32,7 +32,7 @@ public class StddevAgg extends SimpleAggValueSource {
   }
 
   @Override
-  public SlotAcc createSlotAcc(FacetContext fcontext, int numDocs, int numSlots) throws IOException {
+  public SlotAcc createSlotAcc(FacetContext fcontext, long numDocs, int numSlots) throws IOException {
     ValueSource vs = getArg();
 
     if (vs instanceof FieldNameValueSource) {
diff --git a/solr/core/src/java/org/apache/solr/search/facet/SumAgg.java b/solr/core/src/java/org/apache/solr/search/facet/SumAgg.java
index 7cd4b9d..5fe5aed 100644
--- a/solr/core/src/java/org/apache/solr/search/facet/SumAgg.java
+++ b/solr/core/src/java/org/apache/solr/search/facet/SumAgg.java
@@ -34,7 +34,7 @@ public class SumAgg extends SimpleAggValueSource {
   }
 
   @Override
-  public SlotAcc createSlotAcc(FacetContext fcontext, int numDocs, int numSlots) throws IOException {
+  public SlotAcc createSlotAcc(FacetContext fcontext, long numDocs, int numSlots) throws IOException {
     ValueSource vs = getArg();
 
     if (vs instanceof FieldNameValueSource) {
diff --git a/solr/core/src/java/org/apache/solr/search/facet/SumsqAgg.java b/solr/core/src/java/org/apache/solr/search/facet/SumsqAgg.java
index 133e39c..4bb9e67 100644
--- a/solr/core/src/java/org/apache/solr/search/facet/SumsqAgg.java
+++ b/solr/core/src/java/org/apache/solr/search/facet/SumsqAgg.java
@@ -33,7 +33,7 @@ public class SumsqAgg extends SimpleAggValueSource {
   }
 
   @Override
-  public SlotAcc createSlotAcc(FacetContext fcontext, int numDocs, int numSlots) throws IOException {
+  public SlotAcc createSlotAcc(FacetContext fcontext, long numDocs, int numSlots) throws IOException {
     ValueSource vs = getArg();
 
     if (vs instanceof FieldNameValueSource) {
diff --git a/solr/core/src/java/org/apache/solr/search/facet/UnInvertedField.java b/solr/core/src/java/org/apache/solr/search/facet/UnInvertedField.java
index a29c419..0161d07 100644
--- a/solr/core/src/java/org/apache/solr/search/facet/UnInvertedField.java
+++ b/solr/core/src/java/org/apache/solr/search/facet/UnInvertedField.java
@@ -390,7 +390,7 @@ public class UnInvertedField extends DocTermOrds {
     if (doNegative) {
       for (int i=0; i<numTermsInField; i++) {
  //       counts[i] = maxTermCounts[i] - counts[i];
-        counts.incrementCount(i, maxTermCounts[i] - counts.getCount(i)*2);
+        counts.incrementCount(i, maxTermCounts[i] - (int) counts.getCount(i)*2);
       }
     }
 
diff --git a/solr/core/src/java/org/apache/solr/search/facet/UniqueAgg.java b/solr/core/src/java/org/apache/solr/search/facet/UniqueAgg.java
index b31da09..240c1a7 100644
--- a/solr/core/src/java/org/apache/solr/search/facet/UniqueAgg.java
+++ b/solr/core/src/java/org/apache/solr/search/facet/UniqueAgg.java
@@ -42,7 +42,7 @@ public class UniqueAgg extends StrAggValueSource {
   }
 
   @Override
-  public SlotAcc createSlotAcc(FacetContext fcontext, int numDocs, int numSlots) throws IOException {
+  public SlotAcc createSlotAcc(FacetContext fcontext, long numDocs, int numSlots) throws IOException {
     SchemaField sf = fcontext.qcontext.searcher().getSchema().getField(getArg());
     if (sf.multiValued() || sf.getType().multiValuedFieldCache()) {
       if (sf.getType().isPointField()) {
diff --git a/solr/core/src/java/org/apache/solr/search/facet/UniqueBlockAgg.java b/solr/core/src/java/org/apache/solr/search/facet/UniqueBlockAgg.java
index 165fb8d..8d5a0c3 100644
--- a/solr/core/src/java/org/apache/solr/search/facet/UniqueBlockAgg.java
+++ b/solr/core/src/java/org/apache/solr/search/facet/UniqueBlockAgg.java
@@ -79,7 +79,7 @@ public abstract class UniqueBlockAgg extends UniqueAgg {
   }
 
   @Override
-  public abstract SlotAcc createSlotAcc(FacetContext fcontext, int numDocs, int numSlots) throws IOException ;
+  public abstract SlotAcc createSlotAcc(FacetContext fcontext, long numDocs, int numSlots) throws IOException ;
   
   @Override
   public FacetMerger createFacetMerger(Object prototype) {
diff --git a/solr/core/src/java/org/apache/solr/search/facet/UniqueBlockFieldAgg.java b/solr/core/src/java/org/apache/solr/search/facet/UniqueBlockFieldAgg.java
index 3f7f949..fddb32d 100644
--- a/solr/core/src/java/org/apache/solr/search/facet/UniqueBlockFieldAgg.java
+++ b/solr/core/src/java/org/apache/solr/search/facet/UniqueBlockFieldAgg.java
@@ -27,7 +27,7 @@ public class UniqueBlockFieldAgg extends UniqueBlockAgg {
   }
 
   @Override
-  public SlotAcc createSlotAcc(FacetContext fcontext, int numDocs, int numSlots) throws IOException {
+  public SlotAcc createSlotAcc(FacetContext fcontext, long numDocs, int numSlots) throws IOException {
     final String fieldName = getArg();
     SchemaField sf = fcontext.qcontext.searcher().getSchema().getField(fieldName);
     if (sf.multiValued() || sf.getType().multiValuedFieldCache()) {
diff --git a/solr/core/src/java/org/apache/solr/search/facet/UniqueBlockQueryAgg.java b/solr/core/src/java/org/apache/solr/search/facet/UniqueBlockQueryAgg.java
index 3cc46d8..885725d 100644
--- a/solr/core/src/java/org/apache/solr/search/facet/UniqueBlockQueryAgg.java
+++ b/solr/core/src/java/org/apache/solr/search/facet/UniqueBlockQueryAgg.java
@@ -65,7 +65,7 @@ public class UniqueBlockQueryAgg extends UniqueBlockAgg {
   }
 
   @Override
-  public SlotAcc createSlotAcc(FacetContext fcontext, int numDocs, int numSlots) throws IOException {
+  public SlotAcc createSlotAcc(FacetContext fcontext, long numDocs, int numSlots) throws IOException {
     return new UniqueBlockQuerySlotAcc(fcontext, query, numSlots);
   }
 }
diff --git a/solr/core/src/java/org/apache/solr/search/facet/VarianceAgg.java b/solr/core/src/java/org/apache/solr/search/facet/VarianceAgg.java
index f04a073..892f5c5 100644
--- a/solr/core/src/java/org/apache/solr/search/facet/VarianceAgg.java
+++ b/solr/core/src/java/org/apache/solr/search/facet/VarianceAgg.java
@@ -31,7 +31,7 @@ public class VarianceAgg extends SimpleAggValueSource {
   }
 
   @Override
-  public SlotAcc createSlotAcc(FacetContext fcontext, int numDocs, int numSlots) throws IOException {
+  public SlotAcc createSlotAcc(FacetContext fcontext, long numDocs, int numSlots) throws IOException {
     ValueSource vs = getArg();
 
     if (vs instanceof FieldNameValueSource) {
diff --git a/solr/core/src/test/org/apache/solr/schema/CurrencyFieldTypeTest.java b/solr/core/src/test/org/apache/solr/schema/CurrencyFieldTypeTest.java
index 6556125..c63a860 100644
--- a/solr/core/src/test/org/apache/solr/schema/CurrencyFieldTypeTest.java
+++ b/solr/core/src/test/org/apache/solr/schema/CurrencyFieldTypeTest.java
@@ -518,16 +518,16 @@ public class CurrencyFieldTypeTest extends SolrTestCaseJ4 {
                   "{ xxx : { type:range, field:" + fieldName + ", " +
                   "          start:'4.00"+suffix+"', gap:'1.00"+suffix+"', end:'11.00"+suffix+"', other:all } }")
               ,"count(//lst[@name='xxx']/arr[@name='buckets']/lst)=7"
-              ,"//lst[@name='xxx']/arr[@name='buckets']/lst[int[@name='count'][.='1']][str[@name='val'][.='4.00,USD']]"
-              ,"//lst[@name='xxx']/arr[@name='buckets']/lst[int[@name='count'][.='0']][str[@name='val'][.='5.00,USD']]"
-              ,"//lst[@name='xxx']/arr[@name='buckets']/lst[int[@name='count'][.='0']][str[@name='val'][.='6.00,USD']]"
-              ,"//lst[@name='xxx']/arr[@name='buckets']/lst[int[@name='count'][.='1']][str[@name='val'][.='7.00,USD']]"
-              ,"//lst[@name='xxx']/arr[@name='buckets']/lst[int[@name='count'][.='0']][str[@name='val'][.='8.00,USD']]"
-              ,"//lst[@name='xxx']/arr[@name='buckets']/lst[int[@name='count'][.='0']][str[@name='val'][.='9.00,USD']]"
-              ,"//lst[@name='xxx']/arr[@name='buckets']/lst[int[@name='count'][.='1']][str[@name='val'][.='10.00,USD']]"
-              ,"//lst[@name='xxx']/lst[@name='before' ]/int[@name='count'][.='1']"
-              ,"//lst[@name='xxx']/lst[@name='after'  ]/int[@name='count'][.='1']"
-              ,"//lst[@name='xxx']/lst[@name='between']/int[@name='count'][.='3']"
+              ,"//lst[@name='xxx']/arr[@name='buckets']/lst[long[@name='count'][.='1']][str[@name='val'][.='4.00,USD']]"
+              ,"//lst[@name='xxx']/arr[@name='buckets']/lst[long[@name='count'][.='0']][str[@name='val'][.='5.00,USD']]"
+              ,"//lst[@name='xxx']/arr[@name='buckets']/lst[long[@name='count'][.='0']][str[@name='val'][.='6.00,USD']]"
+              ,"//lst[@name='xxx']/arr[@name='buckets']/lst[long[@name='count'][.='1']][str[@name='val'][.='7.00,USD']]"
+              ,"//lst[@name='xxx']/arr[@name='buckets']/lst[long[@name='count'][.='0']][str[@name='val'][.='8.00,USD']]"
+              ,"//lst[@name='xxx']/arr[@name='buckets']/lst[long[@name='count'][.='0']][str[@name='val'][.='9.00,USD']]"
+              ,"//lst[@name='xxx']/arr[@name='buckets']/lst[long[@name='count'][.='1']][str[@name='val'][.='10.00,USD']]"
+              ,"//lst[@name='xxx']/lst[@name='before' ]/long[@name='count'][.='1']"
+              ,"//lst[@name='xxx']/lst[@name='after'  ]/long[@name='count'][.='1']"
+              ,"//lst[@name='xxx']/lst[@name='between']/long[@name='count'][.='3']"
               );
     }
 
@@ -552,13 +552,13 @@ public class CurrencyFieldTypeTest extends SolrTestCaseJ4 {
                 "{ xxx : { type:range, mincount:1, field:" + fieldName +
                 ", start:'0.00,USD', gap:'1.00,USD', end:'11.00,USD', other:all } }")
             ,"count(//lst[@name='xxx']/arr[@name='buckets']/lst)=4"
-            ,"//lst[@name='xxx']/arr[@name='buckets']/lst[int[@name='count'][.='1']][str[@name='val'][.='3.00,USD']]"
-            ,"//lst[@name='xxx']/arr[@name='buckets']/lst[int[@name='count'][.='1']][str[@name='val'][.='4.00,USD']]"
-            ,"//lst[@name='xxx']/arr[@name='buckets']/lst[int[@name='count'][.='1']][str[@name='val'][.='7.00,USD']]"
-            ,"//lst[@name='xxx']/arr[@name='buckets']/lst[int[@name='count'][.='1']][str[@name='val'][.='10.00,USD']]"
-            ,"//lst[@name='xxx']/lst[@name='before' ]/int[@name='count'][.='0']"
-            ,"//lst[@name='xxx']/lst[@name='after'  ]/int[@name='count'][.='1']"
-            ,"//lst[@name='xxx']/lst[@name='between']/int[@name='count'][.='4']"
+            ,"//lst[@name='xxx']/arr[@name='buckets']/lst[long[@name='count'][.='1']][str[@name='val'][.='3.00,USD']]"
+            ,"//lst[@name='xxx']/arr[@name='buckets']/lst[long[@name='count'][.='1']][str[@name='val'][.='4.00,USD']]"
+            ,"//lst[@name='xxx']/arr[@name='buckets']/lst[long[@name='count'][.='1']][str[@name='val'][.='7.00,USD']]"
+            ,"//lst[@name='xxx']/arr[@name='buckets']/lst[long[@name='count'][.='1']][str[@name='val'][.='10.00,USD']]"
+            ,"//lst[@name='xxx']/lst[@name='before' ]/long[@name='count'][.='0']"
+            ,"//lst[@name='xxx']/lst[@name='after'  ]/long[@name='count'][.='1']"
+            ,"//lst[@name='xxx']/lst[@name='between']/long[@name='count'][.='4']"
             );
 
     // NOTE: because of asymetric EUR exchange rate, these buckets are diff then the similar looking USD based request above
@@ -587,16 +587,16 @@ public class CurrencyFieldTypeTest extends SolrTestCaseJ4 {
             req("fl", "*,score", "q", "*:*", "rows", "0", "json.facet",
                 "{ xxx : { type:range, field:" + fieldName + ", start:'8.00,EUR', gap:'2.00,EUR', end:'22.00,EUR', other:all } }")
             ,"count(//lst[@name='xxx']/arr[@name='buckets']/lst)=7"
-            ,"//lst[@name='xxx']/arr[@name='buckets']/lst[int[@name='count'][.='0']][str[@name='val'][.='8.00,EUR']]"
-            ,"//lst[@name='xxx']/arr[@name='buckets']/lst[int[@name='count'][.='0']][str[@name='val'][.='10.00,EUR']]"
-            ,"//lst[@name='xxx']/arr[@name='buckets']/lst[int[@name='count'][.='1']][str[@name='val'][.='12.00,EUR']]"
-            ,"//lst[@name='xxx']/arr[@name='buckets']/lst[int[@name='count'][.='1']][str[@name='val'][.='14.00,EUR']]"
-            ,"//lst[@name='xxx']/arr[@name='buckets']/lst[int[@name='count'][.='0']][str[@name='val'][.='16.00,EUR']]"
-            ,"//lst[@name='xxx']/arr[@name='buckets']/lst[int[@name='count'][.='0']][str[@name='val'][.='18.00,EUR']]"
-            ,"//lst[@name='xxx']/arr[@name='buckets']/lst[int[@name='count'][.='0']][str[@name='val'][.='20.00,EUR']]"
-            ,"//lst[@name='xxx']/lst[@name='before' ]/int[@name='count'][.='2']"
-            ,"//lst[@name='xxx']/lst[@name='after'  ]/int[@name='count'][.='1']"
-            ,"//lst[@name='xxx']/lst[@name='between']/int[@name='count'][.='2']"
+            ,"//lst[@name='xxx']/arr[@name='buckets']/lst[long[@name='count'][.='0']][str[@name='val'][.='8.00,EUR']]"
+            ,"//lst[@name='xxx']/arr[@name='buckets']/lst[long[@name='count'][.='0']][str[@name='val'][.='10.00,EUR']]"
+            ,"//lst[@name='xxx']/arr[@name='buckets']/lst[long[@name='count'][.='1']][str[@name='val'][.='12.00,EUR']]"
+            ,"//lst[@name='xxx']/arr[@name='buckets']/lst[long[@name='count'][.='1']][str[@name='val'][.='14.00,EUR']]"
+            ,"//lst[@name='xxx']/arr[@name='buckets']/lst[long[@name='count'][.='0']][str[@name='val'][.='16.00,EUR']]"
+            ,"//lst[@name='xxx']/arr[@name='buckets']/lst[long[@name='count'][.='0']][str[@name='val'][.='18.00,EUR']]"
+            ,"//lst[@name='xxx']/arr[@name='buckets']/lst[long[@name='count'][.='0']][str[@name='val'][.='20.00,EUR']]"
+            ,"//lst[@name='xxx']/lst[@name='before' ]/long[@name='count'][.='2']"
+            ,"//lst[@name='xxx']/lst[@name='after'  ]/long[@name='count'][.='1']"
+            ,"//lst[@name='xxx']/lst[@name='between']/long[@name='count'][.='2']"
             );
 
     
@@ -627,16 +627,16 @@ public class CurrencyFieldTypeTest extends SolrTestCaseJ4 {
             req("fl", "*,score", "q", "*:*", "rows", "0", "json.facet",
                 "{ xxx : { type:range, field:" + fieldName + ", start:'2.00,GBP', gap:'0.50,GBP', end:'5.50,GBP', other:all } }")
             ,"count(//lst[@name='xxx']/arr[@name='buckets']/lst)=7"
-            ,"//lst[@name='xxx']/arr[@name='buckets']/lst[int[@name='count'][.='1']][str[@name='val'][.='2.00,GBP']]"
-            ,"//lst[@name='xxx']/arr[@name='buckets']/lst[int[@name='count'][.='0']][str[@name='val'][.='2.50,GBP']]"
-            ,"//lst[@name='xxx']/arr[@name='buckets']/lst[int[@name='count'][.='0']][str[@name='val'][.='3.00,GBP']]"
-            ,"//lst[@name='xxx']/arr[@name='buckets']/lst[int[@name='count'][.='1']][str[@name='val'][.='3.50,GBP']]"
-            ,"//lst[@name='xxx']/arr[@name='buckets']/lst[int[@name='count'][.='0']][str[@name='val'][.='4.00,GBP']]"
-            ,"//lst[@name='xxx']/arr[@name='buckets']/lst[int[@name='count'][.='0']][str[@name='val'][.='4.50,GBP']]"
-            ,"//lst[@name='xxx']/arr[@name='buckets']/lst[int[@name='count'][.='1']][str[@name='val'][.='5.00,GBP']]"
-            ,"//lst[@name='xxx']/lst[@name='before' ]/int[@name='count'][.='0']"
-            ,"//lst[@name='xxx']/lst[@name='after'  ]/int[@name='count'][.='2']"
-            ,"//lst[@name='xxx']/lst[@name='between']/int[@name='count'][.='3']"
+            ,"//lst[@name='xxx']/arr[@name='buckets']/lst[long[@name='count'][.='1']][str[@name='val'][.='2.00,GBP']]"
+            ,"//lst[@name='xxx']/arr[@name='buckets']/lst[long[@name='count'][.='0']][str[@name='val'][.='2.50,GBP']]"
+            ,"//lst[@name='xxx']/arr[@name='buckets']/lst[long[@name='count'][.='0']][str[@name='val'][.='3.00,GBP']]"
+            ,"//lst[@name='xxx']/arr[@name='buckets']/lst[long[@name='count'][.='1']][str[@name='val'][.='3.50,GBP']]"
+            ,"//lst[@name='xxx']/arr[@name='buckets']/lst[long[@name='count'][.='0']][str[@name='val'][.='4.00,GBP']]"
+            ,"//lst[@name='xxx']/arr[@name='buckets']/lst[long[@name='count'][.='0']][str[@name='val'][.='4.50,GBP']]"
+            ,"//lst[@name='xxx']/arr[@name='buckets']/lst[long[@name='count'][.='1']][str[@name='val'][.='5.00,GBP']]"
+            ,"//lst[@name='xxx']/lst[@name='before' ]/long[@name='count'][.='0']"
+            ,"//lst[@name='xxx']/lst[@name='after'  ]/long[@name='count'][.='2']"
+            ,"//lst[@name='xxx']/lst[@name='between']/long[@name='count'][.='3']"
             );
 
     assertQ("Ensure that we can set a gap in a currency other than the start and end currencies (facet.range)",
@@ -663,17 +663,17 @@ public class CurrencyFieldTypeTest extends SolrTestCaseJ4 {
             req("fl", "*,score", "q", "*:*", "rows", "0", "json.facet",
                 "{ xxx : { type:range, field:" + fieldName + ", start:'4.00,USD', gap:'0.50,GBP', end:'11.00,USD', other:all } }")
             ,"count(//lst[@name='xxx']/arr[@name='buckets']/lst)=7"
-            ,"//lst[@name='xxx']/arr[@name='buckets']/lst[int[@name='count'][.='1']][str[@name='val'][.='4.00,USD']]"
-            ,"//lst[@name='xxx']/arr[@name='buckets']/lst[int[@name='count'][.='0']][str[@name='val'][.='5.00,USD']]"
-            ,"//lst[@name='xxx']/arr[@name='buckets']/lst[int[@name='count'][.='0']][str[@name='val'][.='6.00,USD']]"
-            ,"//lst[@name='xxx']/arr[@name='buckets']/lst[int[@name='count'][.='1']][str[@name='val'][.='7.00,USD']]"
-            ,"//lst[@name='xxx']/arr[@name='buckets']/lst[int[@name='count'][.='0']][str[@name='val'][.='8.00,USD']]"
-            ,"//lst[@name='xxx']/arr[@name='buckets']/lst[int[@name='count'][.='0']][str[@name='val'][.='9.00,USD']]"
-            ,"//lst[@name='xxx']/arr[@name='buckets']/lst[int[@name='count'][.='1']][str[@name='val'][.='10.00,USD']]"
+            ,"//lst[@name='xxx']/arr[@name='buckets']/lst[long[@name='count'][.='1']][str[@name='val'][.='4.00,USD']]"
+            ,"//lst[@name='xxx']/arr[@name='buckets']/lst[long[@name='count'][.='0']][str[@name='val'][.='5.00,USD']]"
+            ,"//lst[@name='xxx']/arr[@name='buckets']/lst[long[@name='count'][.='0']][str[@name='val'][.='6.00,USD']]"
+            ,"//lst[@name='xxx']/arr[@name='buckets']/lst[long[@name='count'][.='1']][str[@name='val'][.='7.00,USD']]"
+            ,"//lst[@name='xxx']/arr[@name='buckets']/lst[long[@name='count'][.='0']][str[@name='val'][.='8.00,USD']]"
+            ,"//lst[@name='xxx']/arr[@name='buckets']/lst[long[@name='count'][.='0']][str[@name='val'][.='9.00,USD']]"
+            ,"//lst[@name='xxx']/arr[@name='buckets']/lst[long[@name='count'][.='1']][str[@name='val'][.='10.00,USD']]"
             
-            ,"//lst[@name='xxx']/lst[@name='before' ]/int[@name='count'][.='1']"
-            ,"//lst[@name='xxx']/lst[@name='after'  ]/int[@name='count'][.='1']"
-            ,"//lst[@name='xxx']/lst[@name='between']/int[@name='count'][.='3']"
+            ,"//lst[@name='xxx']/lst[@name='before' ]/long[@name='count'][.='1']"
+            ,"//lst[@name='xxx']/lst[@name='after'  ]/long[@name='count'][.='1']"
+            ,"//lst[@name='xxx']/lst[@name='between']/long[@name='count'][.='3']"
             );
 
     for (SolrParams facet : Arrays.asList(params("facet", "true",
diff --git a/solr/core/src/test/org/apache/solr/schema/TestSortableTextField.java b/solr/core/src/test/org/apache/solr/schema/TestSortableTextField.java
index 068273d..571d625 100644
--- a/solr/core/src/test/org/apache/solr/schema/TestSortableTextField.java
+++ b/solr/core/src/test/org/apache/solr/schema/TestSortableTextField.java
@@ -193,9 +193,9 @@ public class TestSortableTextField extends SolrTestCaseJ4 {
         assertQ(req("q", search + ":cow", "rows", "0", 
                     "json.facet", "{x:{ type: terms, field:'" + facet + "', mincount:0 }}")
                 , "//*[@numFound='3']"
-                , jpre + "lst[str[@name='val'][.='how now brown cow ?']][int[@name='count'][.=2]]"
-                , jpre + "lst[str[@name='val'][.='holy cow !']][int[@name='count'][.=1]]"
-                , jpre + "lst[str[@name='val'][.='dog and cat']][int[@name='count'][.=0]]"
+                , jpre + "lst[str[@name='val'][.='how now brown cow ?']][long[@name='count'][.=2]]"
+                , jpre + "lst[str[@name='val'][.='holy cow !']][long[@name='count'][.=1]]"
+                , jpre + "lst[str[@name='val'][.='dog and cat']][long[@name='count'][.=0]]"
                 );
         
       }
diff --git a/solr/core/src/test/org/apache/solr/search/CurrencyRangeFacetCloudTest.java b/solr/core/src/test/org/apache/solr/search/CurrencyRangeFacetCloudTest.java
index 50ece14..2afe497 100644
--- a/solr/core/src/test/org/apache/solr/search/CurrencyRangeFacetCloudTest.java
+++ b/solr/core/src/test/org/apache/solr/search/CurrencyRangeFacetCloudTest.java
@@ -50,7 +50,7 @@ public class CurrencyRangeFacetCloudTest extends SolrCloudTestCase {
   private static String FIELD = null; // randomized
 
   private static final List<String> STR_VALS = Arrays.asList("x0", "x1", "x2");
-  // NOTE: in our test conversions EUR uses an asynetric echange rate
+  // NOTE: in our test conversions EUR uses an asynetric exchange rate
   // these are the equivalent values relative to:                                USD        EUR        GBP
   private static final List<String> VALUES = Arrays.asList("10.00,USD",     // 10.00,USD  25.00,EUR   5.00,GBP
                                                            "15.00,EUR",     //  7.50,USD  15.00,EUR   7.50,GBP
@@ -176,9 +176,9 @@ public class CurrencyRangeFacetCloudTest extends SolrCloudTestCase {
           
           final NamedList<Object> foo = ((NamedList<NamedList<Object>>)rsp.getResponse().get("facets")).get("foo");
           
-          assertEqualsHACK("before", 3L, ((NamedList)foo.get("before")).get("count"));
-          assertEqualsHACK("after", 3L, ((NamedList)foo.get("after")).get("count"));
-          assertEqualsHACK("between", 9L, ((NamedList)foo.get("between")).get("count"));
+          assertEquals("before", 3L, ((NamedList)foo.get("before")).get("count"));
+          assertEquals("after", 3L, ((NamedList)foo.get("after")).get("count"));
+          assertEquals("between", 9L, ((NamedList)foo.get("between")).get("count"));
           
           final List<NamedList> buckets = (List<NamedList>) foo.get("buckets");
           
@@ -187,14 +187,14 @@ public class CurrencyRangeFacetCloudTest extends SolrCloudTestCase {
             for (int i = 0; i < 3; i++) {
               NamedList bucket = buckets.get(i);
               assertEquals((4 + (3 * i)) + ".00,USD", bucket.get("val"));
-              assertEqualsHACK("bucket #" + i, 3L, bucket.get("count"));
+              assertEquals("bucket #" + i, 3L, bucket.get("count"));
             }
           } else {
             assertEquals(7, buckets.size());
             for (int i = 0; i < 7; i++) {
               NamedList bucket = buckets.get(i);
               assertEquals((4 + i) + ".00,USD", bucket.get("val"));
-              assertEqualsHACK("bucket #" + i, (i == 0 || i == 3 || i == 6) ? 3L : 0L, bucket.get("count"));
+              assertEquals("bucket #" + i, (i == 0 || i == 3 || i == 6) ? 3L : 0L, bucket.get("count"));
             }
           }
         } catch (AssertionError|RuntimeException ae) {
@@ -268,9 +268,9 @@ public class CurrencyRangeFacetCloudTest extends SolrCloudTestCase {
         
         final NamedList<Object> foo = ((NamedList<NamedList<Object>>)rsp.getResponse().get("facets")).get("foo");
         
-        assertEqualsHACK("before", 6L, ((NamedList)foo.get("before")).get("count"));
-        assertEqualsHACK("after", 3L, ((NamedList)foo.get("after")).get("count"));
-        assertEqualsHACK("between", 6L, ((NamedList)foo.get("between")).get("count"));
+        assertEquals("before", 6L, ((NamedList)foo.get("before")).get("count"));
+        assertEquals("after", 3L, ((NamedList)foo.get("after")).get("count"));
+        assertEquals("between", 6L, ((NamedList)foo.get("between")).get("count"));
         
         final List<NamedList> buckets = (List<NamedList>) foo.get("buckets");
         
@@ -279,14 +279,14 @@ public class CurrencyRangeFacetCloudTest extends SolrCloudTestCase {
           for (int i = 0; i < 2; i++) {
             NamedList bucket = buckets.get(i);
             assertEquals((12 + (i * 2)) + ".00,EUR", bucket.get("val"));
-            assertEqualsHACK("bucket #" + i, 3L, bucket.get("count"));
+            assertEquals("bucket #" + i, 3L, bucket.get("count"));
           }
         } else {
           assertEquals(7, buckets.size());
           for (int i = 0; i < 7; i++) {
             NamedList bucket = buckets.get(i);
             assertEquals((8 + (i * 2)) + ".00,EUR", bucket.get("val"));
-            assertEqualsHACK("bucket #" + i, (i == 2 || i == 3) ? 3L : 0L, bucket.get("count"));
+            assertEquals("bucket #" + i, (i == 2 || i == 3) ? 3L : 0L, bucket.get("count"));
           }
         }
       } catch (AssertionError|RuntimeException ae) {
@@ -365,9 +365,9 @@ public class CurrencyRangeFacetCloudTest extends SolrCloudTestCase {
         
         // sanity check our high level expectations...
         assertEquals("bar num buckets", 2, bar_buckets.size());
-        assertEqualsHACK("before count", 0L, before.get("count"));
-        assertEqualsHACK("between count", 8L, between.get("count"));
-        assertEqualsHACK("after count", 2L, after.get("count"));
+        assertEquals("before count", 0L, before.get("count"));
+        assertEquals("between count", 8L, between.get("count"));
+        assertEquals("after count", 2L, after.get("count"));
         
         // drill into the various buckets...
         
@@ -378,15 +378,15 @@ public class CurrencyRangeFacetCloudTest extends SolrCloudTestCase {
         for (int i = 0; i < 2; i++) {
           final NamedList<Object> bucket = bar_buckets.get(i);
           assertEquals((i * 10) + ".00,EUR", bucket.get("val"));
-          assertEqualsHACK("bucket #" + i, 4L, bucket.get("count"));
+          assertEquals("bucket #" + i, 4L, bucket.get("count"));
           final List<NamedList<Object>> foo_buckets = ((NamedList<List<NamedList<Object>>>)bucket.get("foo")).get("buckets");
           assertEquals("bucket #" + i + " foo num buckets", 2, foo_buckets.size());
           assertEquals("bucket #" + i + " foo top term", (0==i ? "x2" : "x0"), foo_buckets.get(0).get("val"));
-          assertEqualsHACK("bucket #" + i + " foo top count", 2, foo_buckets.get(0).get("count"));
+          assertEquals("bucket #" + i + " foo top count", 2L, foo_buckets.get(0).get("count"));
           // NOTE: we can't make any assertions about the 2nd val..
           // our limit + randomized sharding could result in either remaining term being picked.
-          // but for eiter term, the count should be exactly the same...
-          assertEqualsHACK("bucket #" + i + " foo 2nd count", 1, foo_buckets.get(1).get("count"));
+          // but for either term, the count should be exactly the same...
+          assertEquals("bucket #" + i + " foo 2nd count", 1L, foo_buckets.get(1).get("count"));
         }
         
         { // between...
@@ -394,9 +394,9 @@ public class CurrencyRangeFacetCloudTest extends SolrCloudTestCase {
           assertEquals("between num buckets", 2, buckets.size());
           // the counts should both be 3, and the term order should break the tie...
           assertEquals("between bucket top", "x0", buckets.get(0).get("val"));
-          assertEqualsHACK("between bucket top count", 3L, buckets.get(0).get("count"));
+          assertEquals("between bucket top count", 3L, buckets.get(0).get("count"));
           assertEquals("between bucket 2nd", "x2", buckets.get(1).get("val"));
-          assertEqualsHACK("between bucket 2nd count", 3L, buckets.get(1).get("count"));
+          assertEquals("between bucket 2nd count", 3L, buckets.get(1).get("count"));
         }
         
         { // after...
@@ -404,9 +404,9 @@ public class CurrencyRangeFacetCloudTest extends SolrCloudTestCase {
           assertEquals("after num buckets", 2, buckets.size());
           // the counts should both be 1, and the term order should break the tie...
           assertEquals("after bucket top", "x1", buckets.get(0).get("val"));
-          assertEqualsHACK("after bucket top count", 1L, buckets.get(0).get("count"));
+          assertEquals("after bucket top count", 1L, buckets.get(0).get("count"));
           assertEquals("after bucket 2nd", "x2", buckets.get(1).get("val"));
-          assertEqualsHACK("after bucket 2nd count", 1L, buckets.get(1).get("count"));
+          assertEquals("after bucket 2nd count", 1L, buckets.get(1).get("count"));
         }
         
       } catch (AssertionError|RuntimeException ae) {
@@ -449,15 +449,15 @@ public class CurrencyRangeFacetCloudTest extends SolrCloudTestCase {
         final List<NamedList<Object>> foo_buckets = (List<NamedList<Object>>) foo.get("buckets");
         assertEquals(1, foo_buckets.size());
         assertEquals("x2", foo_buckets.get(0).get("val"));
-        assertEqualsHACK("foo bucket count", 5L, foo_buckets.get(0).get("count"));
+        assertEquals("foo bucket count", 5L, foo_buckets.get(0).get("count"));
         
         final NamedList<Object> bar = (NamedList<Object>)foo_buckets.get(0).get("bar");
         
         // these are the 'x2' specific counts, based on our fq...
         
-        assertEqualsHACK("before", 2L, ((NamedList)bar.get("before")).get("count"));
-        assertEqualsHACK("after", 1L, ((NamedList)bar.get("after")).get("count"));
-        assertEqualsHACK("between", 2L, ((NamedList)bar.get("between")).get("count"));
+        assertEquals("before", 2L, ((NamedList)bar.get("before")).get("count"));
+        assertEquals("after", 1L, ((NamedList)bar.get("after")).get("count"));
+        assertEquals("between", 2L, ((NamedList)bar.get("between")).get("count"));
         
         final List<NamedList> buckets = (List<NamedList>) bar.get("buckets");
         assertEquals(7, buckets.size());
@@ -465,7 +465,7 @@ public class CurrencyRangeFacetCloudTest extends SolrCloudTestCase {
           NamedList bucket = buckets.get(i);
           assertEquals((8 + (i * 2)) + ".00,EUR", bucket.get("val"));
           // 12,EUR & 15,EUR are the 2 values that align with x2 docs
-          assertEqualsHACK("bucket #" + i, (i == 2 || i == 3) ? 1L : 0L, bucket.get("count"));
+          assertEquals("bucket #" + i, (i == 2 || i == 3) ? 1L : 0L, bucket.get("count"));
         }
       } catch (AssertionError|RuntimeException ae) {
         throw new AssertionError(solrQuery.toString() + " -> " + rsp.toString() + " ===> " + ae.getMessage(), ae);
@@ -473,14 +473,4 @@ public class CurrencyRangeFacetCloudTest extends SolrCloudTestCase {
     }
   }
 
-  /**
-   * HACK to work around SOLR-11775.
-   * Asserts that the 'actual' argument is a (non-null) Number, then compares it's 'longValue' to the 'expected' argument
-   */
-  private static void assertEqualsHACK(String msg, long expected, Object actual) {
-    assertNotNull(msg, actual);
-    assertTrue(msg + " ... NOT A NUMBER: " + actual.getClass(), Number.class.isInstance(actual));
-    assertEquals(msg, expected, ((Number)actual).longValue());
-  }
-  
 }
diff --git a/solr/core/src/test/org/apache/solr/search/facet/DebugAgg.java b/solr/core/src/test/org/apache/solr/search/facet/DebugAgg.java
index a8e0c58..ee7f0e8 100644
--- a/solr/core/src/test/org/apache/solr/search/facet/DebugAgg.java
+++ b/solr/core/src/test/org/apache/solr/search/facet/DebugAgg.java
@@ -68,7 +68,7 @@ class DebugAgg extends AggValueSource {
   }
 
   @Override
-  public SlotAcc createSlotAcc(FacetContext fcontext, int numDocs, int numSlots) throws IOException {
+  public SlotAcc createSlotAcc(FacetContext fcontext, long numDocs, int numSlots) throws IOException {
     return new Acc(fcontext, numDocs, numSlots, inner.createSlotAcc(fcontext, numDocs, numSlots));
   }
 
@@ -91,10 +91,10 @@ class DebugAgg extends AggValueSource {
     public static Acc last;
 
     public SlotAcc sub;
-    public int numDocs;
+    public long numDocs;
     public int numSlots;
 
-    public Acc(FacetContext fcontext, int numDocs, int numSlots, SlotAcc sub) {
+    public Acc(FacetContext fcontext, long numDocs, int numSlots, SlotAcc sub) {
       super(fcontext);
       this.last = this;
       this.numDocs = numDocs;
@@ -173,7 +173,7 @@ class DebugAgg extends AggValueSource {
     }
     
     @Override
-    public SlotAcc createSlotAcc(FacetContext fcontext, int numDocs, int numSlots) {
+    public SlotAcc createSlotAcc(FacetContext fcontext, long numDocs, int numSlots) {
       return new NumShardsAcc(fcontext, numDocs, numSlots);
     }
     
@@ -188,7 +188,7 @@ class DebugAgg extends AggValueSource {
     }
     
     public static class NumShardsAcc extends SlotAcc {
-      public NumShardsAcc(FacetContext fcontext, int numDocs, int numSlots) {
+      public NumShardsAcc(FacetContext fcontext, long numDocs, int numSlots) {
         super(fcontext);
       }
       
diff --git a/solr/core/src/test/org/apache/solr/search/facet/DistributedFacetSimpleRefinementLongTailTest.java b/solr/core/src/test/org/apache/solr/search/facet/DistributedFacetSimpleRefinementLongTailTest.java
index b611165..a24da43 100644
--- a/solr/core/src/test/org/apache/solr/search/facet/DistributedFacetSimpleRefinementLongTailTest.java
+++ b/solr/core/src/test/org/apache/solr/search/facet/DistributedFacetSimpleRefinementLongTailTest.java
@@ -147,7 +147,7 @@ public class DistributedFacetSimpleRefinementLongTailTest extends BaseDistribute
       for (int j = 0; j < 5; j++) {
         NamedList bucket = shardFooBuckets[i].get(j);
         assertEquals(bucket.toString(), "aaa"+j, bucket.get("val"));
-        assertEquals(bucket.toString(), 100, bucket.get("count"));
+        assertEquals(bucket.toString(), 100L, bucket.get("count"));
       }
     }
     // top 6-10 same on shard0 & shard1
@@ -155,19 +155,19 @@ public class DistributedFacetSimpleRefinementLongTailTest extends BaseDistribute
       for (int j = 5; j < 10; j++) {
         NamedList bucket = shardFooBuckets[i].get(j);
         assertTrue(bucket.toString(), bucket.get("val").toString().startsWith("bbb"));
-        assertEquals(bucket.toString(), 50, bucket.get("count"));
+        assertEquals(bucket.toString(), 50L, bucket.get("count"));
       }
     }
 
     // 6-10 on shard2
     assertEquals("junkA", shardFooBuckets[2].get(5).get("val"));
-    assertEquals(50, shardFooBuckets[2].get(5).get("count"));
+    assertEquals(50L, shardFooBuckets[2].get(5).get("count"));
     assertEquals("tail", shardFooBuckets[2].get(6).get("val"));
-    assertEquals(45, shardFooBuckets[2].get(6).get("count"));
+    assertEquals(45L, shardFooBuckets[2].get(6).get("count"));
     for (int j = 7; j < 10; j++) {
       NamedList bucket = shardFooBuckets[2].get(j);
       assertTrue(bucket.toString(), bucket.get("val").toString().startsWith("ZZZ"));
-      assertEquals(bucket.toString(), 1, bucket.get("count"));
+      assertEquals(bucket.toString(), 1L, bucket.get("count"));
     }
     
     // check 'bar' sub buckets on "tail" from shard2
@@ -176,11 +176,11 @@ public class DistributedFacetSimpleRefinementLongTailTest extends BaseDistribute
       for (int j = 0; j < 5; j++) {
         NamedList bucket = bar_buckets.get(j);
         assertTrue(bucket.toString(), bucket.get("val").toString().startsWith("junkB"));
-        assertEquals(bucket.toString(), 8, bucket.get("count"));
+        assertEquals(bucket.toString(), 8L, bucket.get("count"));
       }
       NamedList bucket = bar_buckets.get(5);
       assertEquals("tailB", bucket.get("val"));
-      assertEquals(5, bucket.get("count"));
+      assertEquals(5L, bucket.get("count"));
     }
   }
 
diff --git a/solr/core/src/test/org/apache/solr/search/facet/RangeFacetCloudTest.java b/solr/core/src/test/org/apache/solr/search/facet/RangeFacetCloudTest.java
index 77663df..f9419de 100644
--- a/solr/core/src/test/org/apache/solr/search/facet/RangeFacetCloudTest.java
+++ b/solr/core/src/test/org/apache/solr/search/facet/RangeFacetCloudTest.java
@@ -741,7 +741,7 @@ public class RangeFacetCloudTest extends SolrCloudTestCase {
         toMerge.add(TERM_MODEL[i]);
       }
 
-      assertEqualsHACK("count", expectedCount, bucket.get("count"));
+      assertEquals("count", expectedCount, bucket.get("count"));
       
       // merge the maps of our range values by summing the (int) values on key collisions
       final Map<String,Long> expectedTermCounts = toMerge.stream()
@@ -766,7 +766,7 @@ public class RangeFacetCloudTest extends SolrCloudTestCase {
           assertNotNull("subfacet bucket with null term: " + subBucket, term);
           final Long expectedTermCount = expectedTermCounts.get(term.toString());
           assertNotNull("unexpected subfacet bucket: " + subBucket, expectedTermCount);
-          assertEqualsHACK("subfacet count for term: " + term, expectedTermCount, subBucket.get("count"));
+          assertEquals("subfacet count for term: " + term, expectedTermCount, subBucket.get("count"));
         }
       }
         
@@ -910,14 +910,4 @@ public class RangeFacetCloudTest extends SolrCloudTestCase {
     return ", other:" + val;
   }
   
-  /**
-   * HACK to work around SOLR-11775.
-   * Asserts that the 'actual' argument is a (non-null) Number, then compares it's 'longValue' to the 'expected' argument
-   */
-  private static void assertEqualsHACK(String msg, long expected, Object actual) {
-    assertNotNull(msg, actual);
-    assertTrue(msg + " ... NOT A NUMBER: " + actual.getClass(), Number.class.isInstance(actual));
-    assertEquals(msg, expected, ((Number)actual).longValue());
-  }
-  
 }
diff --git a/solr/core/src/test/org/apache/solr/search/facet/TestJsonFacets.java b/solr/core/src/test/org/apache/solr/search/facet/TestJsonFacets.java
index 573a800..aea04b3 100644
--- a/solr/core/src/test/org/apache/solr/search/facet/TestJsonFacets.java
+++ b/solr/core/src/test/org/apache/solr/search/facet/TestJsonFacets.java
@@ -3283,6 +3283,64 @@ public class TestJsonFacets extends SolrTestCaseHS {
 
   }
 
+  @Test
+  public void testFacetValueTypes() throws Exception {
+    doFacetValueTypeValidation(Client.localClient());
+  }
+
+  @Test
+  public void testFacetValueTypesDistrib() throws Exception {
+    initServers();
+    Client client = servers.getClient(random().nextInt());
+    client.queryDefaults().set( "shards", servers.getShards(), "debugQuery", Boolean.toString(random().nextBoolean()) );
+    doFacetValueTypeValidation(client);
+  }
+
+  private void doFacetValueTypeValidation(Client client) throws Exception {
+    indexSimple(client);
+
+    client.testXQ(params("q", "*:*", "rows", "0",
+        "json.facet", "{cat_s:{type:terms,field:cat_s,mincount:0,missing:true,allBuckets:true,numBuckets:true,limit:1}}"),
+        "/response/lst[@name='facets']/long[@name='count'][.=6]", // count
+        "/response/lst[@name='facets']/lst[@name='cat_s']/long[@name='numBuckets'][.=2]", // total no of buckets
+        "*[count(/response/lst[@name='facets']/lst[@name='cat_s']/arr[@name='buckets']/lst)=1]", // no of entries
+        "/response/lst[@name='facets']/lst[@name='cat_s']/lst[@name='allBuckets']/long[@name='count'][.=5]", // allBuckets
+        "/response/lst[@name='facets']/lst[@name='cat_s']/lst[@name='missing']/long[@name='count'][.=1]", // missing
+        "/response/lst[@name='facets']/lst[@name='cat_s']/arr[@name='buckets']/lst[1]/str[@name='val'][.='B']", // facet value
+        "/response/lst[@name='facets']/lst[@name='cat_s']/arr[@name='buckets']/lst[1]/long[@name='count'][.='3']" // facet count
+    );
+
+    // aggregations types for string
+    client.testXQ(params("q", "*:*", "rows", "0",
+        "json.facet", "{unique:'unique(cat_s)',hll:'hll(cat_s)',vals:'countvals(cat_s)',missing:'missing(cat_s)'}"),
+        "/response/lst[@name='facets']/long[@name='count'][.=6]", // count
+        "/response/lst[@name='facets']/long[@name='unique'][.=2]", // unique
+        "/response/lst[@name='facets']/long[@name='hll'][.=2]", // hll
+        "/response/lst[@name='facets']/long[@name='vals'][.=5]", // values
+        "/response/lst[@name='facets']/long[@name='missing'][.=1]" // missing
+    );
+
+    // aggregations types for number
+    client.testXQ(params("q", "*:*", "rows", "0",
+        "json.facet", "{unique:'unique(num_i)',hll:'hll(num_i)',vals:'countvals(num_i)',missing:'missing(num_i)'}"),
+        "/response/lst[@name='facets']/long[@name='count'][.=6]", // count
+        "/response/lst[@name='facets']/long[@name='unique'][.=4]", // unique
+        "/response/lst[@name='facets']/long[@name='hll'][.=4]", // hll
+        "/response/lst[@name='facets']/long[@name='vals'][.=5]", // values
+        "/response/lst[@name='facets']/long[@name='missing'][.=1]" // missing
+    );
+
+    // aggregations types for multi-valued number
+    client.testXQ(params("q", "*:*", "rows", "0",
+        "json.facet", "{unique:'unique(num_is)',hll:'hll(num_is)',vals:'countvals(num_is)',missing:'missing(num_is)'}"),
+        "/response/lst[@name='facets']/long[@name='count'][.=6]", // count
+        "/response/lst[@name='facets']/long[@name='unique'][.=7]", // unique
+        "/response/lst[@name='facets']/long[@name='hll'][.=7]", // hll
+        "/response/lst[@name='facets']/long[@name='vals'][.=9]", // values
+        "/response/lst[@name='facets']/long[@name='missing'][.=1]" // missing
+    );
+  }
+
   public void XtestPercentiles() {
     AVLTreeDigest catA = new AVLTreeDigest(100);
     catA.add(4);
diff --git a/solr/core/src/test/org/apache/solr/search/facet/TestJsonRangeFacets.java b/solr/core/src/test/org/apache/solr/search/facet/TestJsonRangeFacets.java
index 0d21636..6c8364c 100644
--- a/solr/core/src/test/org/apache/solr/search/facet/TestJsonRangeFacets.java
+++ b/solr/core/src/test/org/apache/solr/search/facet/TestJsonRangeFacets.java
@@ -394,4 +394,42 @@ public class TestJsonRangeFacets extends SolrTestCaseHS {
         "facets=={count:6, price:{buckets:[{val:\"[*,*)\",count:5}]}}");
   }
 
+  @Test
+  public void testFacetValueTypes() throws Exception {
+    doFacetValueTypeValidation(Client.localClient());
+  }
+
+  @Test
+  public void testFacetValueTypeDistrib() throws Exception {
+    initServers();
+    Client client = servers.getClient(random().nextInt());
+    client.queryDefaults().set( "shards", servers.getShards(), "debugQuery", Boolean.toString(random().nextBoolean()) );
+    doFacetValueTypeValidation(client);
+  }
+
+  private void doFacetValueTypeValidation(Client client) throws Exception {
+    indexSimple(client);
+
+    // range faceting with start, end, and gap
+    client.testXQ(params("q", "*:*", "rows",  "0",
+        "json.facet", "{num:{type: range, field:num_i,start:0,gap:2,end:10,mincount:1,other:all}}"),
+        "/response/lst[@name='facets']/long[@name='count'][.=6]", // count
+        "/response/lst[@name='facets']/lst[@name='num']/arr[@name='buckets']/lst[1]/int[@name='val'][.=2]", // value
+        "/response/lst[@name='facets']/lst[@name='num']/arr[@name='buckets']/lst[1]/long[@name='count'][.=2]", // count
+        "*[count(/response/lst[@name='facets']/lst[@name='num']/arr[@name='buckets']/lst)=2]", // no of entries
+        "/response/lst[@name='facets']/lst[@name='num']/lst[@name='before']/long[@name='count'][.=2]", // before
+        "/response/lst[@name='facets']/lst[@name='num']/lst[@name='after']/long[@name='count'][.=0]", // after
+        "/response/lst[@name='facets']/lst[@name='num']/lst[@name='between']/long[@name='count'][.=3]" // between
+    );
+
+    // range faceting with ranges specified
+    client.testXQ(params("q", "*:*", "rows",  "0",
+        "json.facet", "{num:{type: range, field:num_i,ranges:[{from:0, to:4},{from:-4,to:2}],mincount:1}}"),
+        "/response/lst[@name='facets']/long[@name='count'][.=6]", // count
+        "/response/lst[@name='facets']/lst[@name='num']/arr[@name='buckets']/lst[1]/str[@name='val'][.='[0,4)']", // value
+        "/response/lst[@name='facets']/lst[@name='num']/arr[@name='buckets']/lst[1]/long[@name='count'][.=2]", // count
+        "*[count(/response/lst[@name='facets']/lst[@name='num']/arr[@name='buckets']/lst)=1]" // no of entries
+    );
+  }
+
 }
diff --git a/solr/solr-ref-guide/src/major-changes-in-solr-9.adoc b/solr/solr-ref-guide/src/major-changes-in-solr-9.adoc
index bfb6472..8262de9 100644
--- a/solr/solr-ref-guide/src/major-changes-in-solr-9.adoc
+++ b/solr/solr-ref-guide/src/major-changes-in-solr-9.adoc
@@ -103,6 +103,8 @@ _(raw; not yet edited)_
 
 * SOLR-12720: To change the auto add replica wait period modify the `waitFor` attribute of the `.auto_add_replicas` trigger.
   (marcussorealheis, shalin)
+
+* SOLR-11775: Return long value for facet count in Json Facet module irrespective of number of shards (hossman, Munendra S N)
   
 === Upgrade Prerequisites in Solr 9
 
diff --git a/solr/test-framework/src/java/org/apache/solr/SolrTestCaseHS.java b/solr/test-framework/src/java/org/apache/solr/SolrTestCaseHS.java
index 0e7edfe..3da476a 100644
--- a/solr/test-framework/src/java/org/apache/solr/SolrTestCaseHS.java
+++ b/solr/test-framework/src/java/org/apache/solr/SolrTestCaseHS.java
@@ -16,6 +16,7 @@
  */
 package org.apache.solr;
 
+import javax.xml.xpath.XPathExpressionException;
 import java.io.File;
 import java.io.IOException;
 import java.io.OutputStreamWriter;
@@ -45,6 +46,7 @@ import org.apache.solr.client.solrj.impl.NoOpResponseParser;
 import org.apache.solr.client.solrj.request.QueryRequest;
 import org.apache.solr.client.solrj.request.UpdateRequest;
 import org.apache.solr.client.solrj.response.UpdateResponse;
+import org.apache.solr.common.SolrException;
 import org.apache.solr.common.SolrInputDocument;
 import org.apache.solr.common.params.ModifiableSolrParams;
 import org.apache.solr.common.params.SolrParams;
@@ -54,6 +56,7 @@ import org.apache.solr.request.SolrQueryRequest;
 import org.apache.solr.schema.IndexSchema;
 import org.apache.solr.schema.SchemaField;
 import org.apache.solr.servlet.DirectSolrConnection;
+import org.apache.solr.util.TestHarness;
 import org.noggit.JSONUtil;
 import org.noggit.ObjectBuilder;
 import org.slf4j.Logger;
@@ -145,6 +148,31 @@ public class SolrTestCaseHS extends SolrTestCaseJ4 {
     matchJSON(resp, tests);
   }
 
+  /**
+   * Pass "null" for the client to query to the local server.
+   * Fetches response in xml format and matches with the given set of xpaths
+   */
+  public static void assertQ(SolrClient client, SolrParams args, String... tests) throws Exception {
+    String resp;
+    resp = getQueryResponse(client, "xml", args);
+    try {
+      String results = TestHarness.validateXPath(resp, tests);
+      if (null != results) {
+        String msg = "REQUEST FAILED: xpath=" + results
+            + "\n\txml response was: " + resp
+            + "\n\tparams were:" + args.toQueryString();
+
+        log.error(msg);
+        throw new RuntimeException(msg);
+      }
+    } catch (XPathExpressionException e1) {
+      throw new RuntimeException("XPath is invalid", e1);
+    } catch (Exception e2) {
+      SolrException.log(log,"REQUEST FAILED for params: " + args.toQueryString(), e2);
+      throw new RuntimeException("Exception during query", e2);
+    }
+  }
+
   public static void matchJSON(String response, String... tests) throws Exception {
     boolean failed = false;
 
@@ -256,6 +284,10 @@ public class SolrTestCaseHS extends SolrTestCaseJ4 {
       public  void assertJQ(SolrClient client, SolrParams args, String... tests) throws Exception {
         SolrTestCaseHS.assertJQ(client, args, tests);
       }
+
+      public  void assertQ(SolrClient client, SolrParams args, String... tests) throws Exception {
+        SolrTestCaseHS.assertQ(client, args, tests);
+      }
     }
 
     public static Client localClient = new Client(null, 1);
@@ -299,6 +331,19 @@ public class SolrTestCaseHS extends SolrTestCaseJ4 {
       tester.assertJQ(client, args, tests);
     }
 
+    /**
+     * tests are validated against xml response
+     */
+    public void testXQ(SolrParams args, String... tests) throws Exception {
+      if (queryDefaults != null) {
+        ModifiableSolrParams newParams = params(queryDefaults);
+        newParams.add(args);
+        args = newParams;
+      }
+      SolrClient client = provider==null ? null : provider.client(null, args);
+      tester.assertQ(client, args, tests);
+    }
+
     public Long add(SolrInputDocument sdoc, ModifiableSolrParams params) throws Exception {
       SolrClient client = provider==null ? null : provider.client(sdoc, params);
       return SolrTestCaseHS.add(client, sdoc, params);