@Override
  public Facet reduce(List<Facet> facets) {
    if (facets.size() == 1) {
      return facets.get(0);
    }

    InternalLongTermsFacet first = null;

    TLongIntHashMap aggregated = CacheRecycler.popLongIntMap();
    long missing = 0;
    long total = 0;
    for (Facet facet : facets) {
      TermsFacet termsFacet = (TermsFacet) facet;
      // termsFacet could be of type InternalStringTermsFacet representing unmapped fields
      if (first == null && termsFacet instanceof InternalLongTermsFacet) {
        first = (InternalLongTermsFacet) termsFacet;
      }
      missing += termsFacet.getMissingCount();
      total += termsFacet.getTotalCount();
      for (Entry entry : termsFacet.getEntries()) {
        aggregated.adjustOrPutValue(((LongEntry) entry).term, entry.getCount(), entry.getCount());
      }
    }

    BoundedTreeSet<LongEntry> ordered =
        new BoundedTreeSet<LongEntry>(first.comparatorType.comparator(), first.requiredSize);
    for (TLongIntIterator it = aggregated.iterator(); it.hasNext(); ) {
      it.advance();
      ordered.add(new LongEntry(it.key(), it.value()));
    }
    first.entries = ordered;
    first.missing = missing;
    first.total = total;

    CacheRecycler.pushLongIntMap(aggregated);

    return first;
  }