private BsonField accumulator(String field, Expression expression) {
    Preconditions.checkArgument(expression instanceof Call, "not a call %s", expression);
    final Call call = (Call) expression;
    final Operator op = call.operator();
    Preconditions.checkArgument(AggregationOperators.isAggregation(op), "not an aggregation operator: %s", op);
    final String name = "$" + naming.get(extractPath(expression));
    if (op == AggregationOperators.AVG) {
      return Accumulators.avg(field, name);
    } else if (op == AggregationOperators.COUNT) {
      return Accumulators.sum(field, 1);
    } else if (op == AggregationOperators.MAX) {
      return Accumulators.max(field, name);
    } else if (op == AggregationOperators.MIN) {
      return Accumulators.min(field, name);
    } else if (op == AggregationOperators.SUM) {
      return Accumulators.sum(field, name);
    } else {
      throw new IllegalArgumentException(String.format("Unknown aggregation operator %s from %s", op, expression));
    }
  }
Converts query of type {@code select distinct a, b, c from table} to {@code select a, b, c from table group by a, b, c}
so same pipelines (like {@link Group}) can be (re-)used. Does nothing if this is not a {@code distinct} query.
@param query query to be converted
@return new version of the query with projections copied to {@code groupBy} list or unmodified query.
@throws UnsupportedOperationException if query is "distinct" and {@code groupBy} is not empty
criteria/mongo/src/org/immutables/criteria/mongo/AggregationQuery.java