@Test
  public void testNoBuckets() throws Exception {
    SearchResponse response =
        client()
            .prepareSearch("idx")
            .addAggregation(
                terms("terms")
                    .field("tag")
                    .exclude("tag.*")
                    .subAggregation(sum("sum").field(SINGLE_VALUED_FIELD_NAME)))
            .addAggregation(maxBucket("max_bucket").setBucketsPaths("terms>sum"))
            .execute()
            .actionGet();

    assertSearchResponse(response);

    Terms terms = response.getAggregations().get("terms");
    assertThat(terms, notNullValue());
    assertThat(terms.getName(), equalTo("terms"));
    List<Terms.Bucket> buckets = terms.getBuckets();
    assertThat(buckets.size(), equalTo(0));

    InternalBucketMetricValue maxBucketValue = response.getAggregations().get("max_bucket");
    assertThat(maxBucketValue, notNullValue());
    assertThat(maxBucketValue.getName(), equalTo("max_bucket"));
    assertThat(maxBucketValue.value(), equalTo(Double.NEGATIVE_INFINITY));
    assertThat(maxBucketValue.keys(), equalTo(new String[0]));
  }
  @Test
  public void testDocCount_asSubAgg() throws Exception {
    SearchResponse response =
        client()
            .prepareSearch("idx")
            .addAggregation(
                terms("terms")
                    .field("tag")
                    .order(Order.term(true))
                    .subAggregation(
                        histogram("histo")
                            .field(SINGLE_VALUED_FIELD_NAME)
                            .interval(interval)
                            .extendedBounds((long) minRandomValue, (long) maxRandomValue))
                    .subAggregation(maxBucket("max_bucket").setBucketsPaths("histo>_count")))
            .execute()
            .actionGet();

    assertSearchResponse(response);

    Terms terms = response.getAggregations().get("terms");
    assertThat(terms, notNullValue());
    assertThat(terms.getName(), equalTo("terms"));
    List<Terms.Bucket> termsBuckets = terms.getBuckets();
    assertThat(termsBuckets.size(), equalTo(interval));

    for (int i = 0; i < interval; ++i) {
      Terms.Bucket termsBucket = termsBuckets.get(i);
      assertThat(termsBucket, notNullValue());
      assertThat((String) termsBucket.getKey(), equalTo("tag" + (i % interval)));

      Histogram histo = termsBucket.getAggregations().get("histo");
      assertThat(histo, notNullValue());
      assertThat(histo.getName(), equalTo("histo"));
      List<? extends Bucket> buckets = histo.getBuckets();

      List<String> maxKeys = new ArrayList<>();
      double maxValue = Double.NEGATIVE_INFINITY;
      for (int j = 0; j < numValueBuckets; ++j) {
        Histogram.Bucket bucket = buckets.get(j);
        assertThat(bucket, notNullValue());
        assertThat(((Number) bucket.getKey()).longValue(), equalTo((long) j * interval));
        if (bucket.getDocCount() > maxValue) {
          maxValue = bucket.getDocCount();
          maxKeys = new ArrayList<>();
          maxKeys.add(bucket.getKeyAsString());
        } else if (bucket.getDocCount() == maxValue) {
          maxKeys.add(bucket.getKeyAsString());
        }
      }

      InternalBucketMetricValue maxBucketValue = termsBucket.getAggregations().get("max_bucket");
      assertThat(maxBucketValue, notNullValue());
      assertThat(maxBucketValue.getName(), equalTo("max_bucket"));
      assertThat(maxBucketValue.value(), equalTo(maxValue));
      assertThat(maxBucketValue.keys(), equalTo(maxKeys.toArray(new String[maxKeys.size()])));
    }
  }
  @Test
  public void testMetric_asSubAggOfSingleBucketAgg() throws Exception {
    SearchResponse response =
        client()
            .prepareSearch("idx")
            .addAggregation(
                filter("filter")
                    .filter(termQuery("tag", "tag0"))
                    .subAggregation(
                        histogram("histo")
                            .field(SINGLE_VALUED_FIELD_NAME)
                            .interval(interval)
                            .extendedBounds((long) minRandomValue, (long) maxRandomValue)
                            .subAggregation(sum("sum").field(SINGLE_VALUED_FIELD_NAME)))
                    .subAggregation(maxBucket("max_bucket").setBucketsPaths("histo>sum")))
            .execute()
            .actionGet();

    assertSearchResponse(response);

    Filter filter = response.getAggregations().get("filter");
    assertThat(filter, notNullValue());
    assertThat(filter.getName(), equalTo("filter"));
    Histogram histo = filter.getAggregations().get("histo");
    assertThat(histo, notNullValue());
    assertThat(histo.getName(), equalTo("histo"));
    List<? extends Bucket> buckets = histo.getBuckets();

    List<String> maxKeys = new ArrayList<>();
    double maxValue = Double.NEGATIVE_INFINITY;
    for (int j = 0; j < numValueBuckets; ++j) {
      Histogram.Bucket bucket = buckets.get(j);
      assertThat(bucket, notNullValue());
      assertThat(((Number) bucket.getKey()).longValue(), equalTo((long) j * interval));
      if (bucket.getDocCount() != 0) {
        Sum sum = bucket.getAggregations().get("sum");
        assertThat(sum, notNullValue());
        if (sum.value() > maxValue) {
          maxValue = sum.value();
          maxKeys = new ArrayList<>();
          maxKeys.add(bucket.getKeyAsString());
        } else if (sum.value() == maxValue) {
          maxKeys.add(bucket.getKeyAsString());
        }
      }
    }

    InternalBucketMetricValue maxBucketValue = filter.getAggregations().get("max_bucket");
    assertThat(maxBucketValue, notNullValue());
    assertThat(maxBucketValue.getName(), equalTo("max_bucket"));
    assertThat(maxBucketValue.value(), equalTo(maxValue));
    assertThat(maxBucketValue.keys(), equalTo(maxKeys.toArray(new String[maxKeys.size()])));
  }
  @Test
  public void testMetric_topLevel() throws Exception {
    SearchResponse response =
        client()
            .prepareSearch("idx")
            .addAggregation(
                terms("terms")
                    .field("tag")
                    .subAggregation(sum("sum").field(SINGLE_VALUED_FIELD_NAME)))
            .addAggregation(maxBucket("max_bucket").setBucketsPaths("terms>sum"))
            .execute()
            .actionGet();

    assertSearchResponse(response);

    Terms terms = response.getAggregations().get("terms");
    assertThat(terms, notNullValue());
    assertThat(terms.getName(), equalTo("terms"));
    List<Terms.Bucket> buckets = terms.getBuckets();
    assertThat(buckets.size(), equalTo(interval));

    List<String> maxKeys = new ArrayList<>();
    double maxValue = Double.NEGATIVE_INFINITY;
    for (int i = 0; i < interval; ++i) {
      Terms.Bucket bucket = buckets.get(i);
      assertThat(bucket, notNullValue());
      assertThat((String) bucket.getKey(), equalTo("tag" + (i % interval)));
      assertThat(bucket.getDocCount(), greaterThan(0l));
      Sum sum = bucket.getAggregations().get("sum");
      assertThat(sum, notNullValue());
      if (sum.value() > maxValue) {
        maxValue = sum.value();
        maxKeys = new ArrayList<>();
        maxKeys.add(bucket.getKeyAsString());
      } else if (sum.value() == maxValue) {
        maxKeys.add(bucket.getKeyAsString());
      }
    }

    InternalBucketMetricValue maxBucketValue = response.getAggregations().get("max_bucket");
    assertThat(maxBucketValue, notNullValue());
    assertThat(maxBucketValue.getName(), equalTo("max_bucket"));
    assertThat(maxBucketValue.value(), equalTo(maxValue));
    assertThat(maxBucketValue.keys(), equalTo(maxKeys.toArray(new String[maxKeys.size()])));
  }