Add _bucket_count option to buckets_path
This change adds a new special path to the buckets_path syntax `_bucket_count`. This new option will return the number of buckets for a multi-bucket aggregation, which can then be used in pipeline aggregations. Closes #19553
This commit is contained in:
parent
c7c0faa54d
commit
2c12c3e628
|
@ -43,7 +43,7 @@ public abstract class InternalMultiBucketAggregation<A extends InternalMultiBuck
|
|||
/**
|
||||
* Create a new copy of this {@link Aggregation} with the same settings as
|
||||
* this {@link Aggregation} and contains the provided buckets.
|
||||
*
|
||||
*
|
||||
* @param buckets
|
||||
* the buckets to use in the new {@link Aggregation}
|
||||
* @return the new {@link Aggregation}
|
||||
|
@ -53,7 +53,7 @@ public abstract class InternalMultiBucketAggregation<A extends InternalMultiBuck
|
|||
/**
|
||||
* Create a new {@link InternalBucket} using the provided prototype bucket
|
||||
* and aggregations.
|
||||
*
|
||||
*
|
||||
* @param aggregations
|
||||
* the aggregations for the new bucket
|
||||
* @param prototype
|
||||
|
@ -66,6 +66,8 @@ public abstract class InternalMultiBucketAggregation<A extends InternalMultiBuck
|
|||
public Object getProperty(List<String> path) {
|
||||
if (path.isEmpty()) {
|
||||
return this;
|
||||
} else if (path.get(0).equals("_bucket_count")) {
|
||||
return getBuckets().size();
|
||||
} else {
|
||||
List<? extends Bucket> buckets = getBuckets();
|
||||
Object[] propertyArray = new Object[buckets.size()];
|
||||
|
|
|
@ -380,6 +380,7 @@ public class DateHistogramIT extends ESIntegTestCase {
|
|||
assertThat(histo.getName(), equalTo("histo"));
|
||||
List<? extends Bucket> buckets = histo.getBuckets();
|
||||
assertThat(buckets.size(), equalTo(3));
|
||||
assertThat(histo.getProperty("_bucket_count"), equalTo(3));
|
||||
Object[] propertiesKeys = (Object[]) histo.getProperty("_key");
|
||||
Object[] propertiesDocCounts = (Object[]) histo.getProperty("_count");
|
||||
Object[] propertiesCounts = (Object[]) histo.getProperty("sum.value");
|
||||
|
@ -600,7 +601,7 @@ public class DateHistogramIT extends ESIntegTestCase {
|
|||
assertThat(histo.getBuckets().size(), equalTo(4));
|
||||
|
||||
// TODO: use diamond once JI-9019884 is fixed
|
||||
List<Histogram.Bucket> buckets = new ArrayList<Histogram.Bucket>(histo.getBuckets());
|
||||
List<Histogram.Bucket> buckets = new ArrayList<>(histo.getBuckets());
|
||||
|
||||
Histogram.Bucket bucket = buckets.get(0);
|
||||
assertThat(bucket, notNullValue());
|
||||
|
|
|
@ -137,7 +137,7 @@ public class DateRangeIT extends ESIntegTestCase {
|
|||
assertThat(range.getBuckets().size(), equalTo(3));
|
||||
|
||||
// TODO: use diamond once JI-9019884 is fixed
|
||||
List<Range.Bucket> buckets = new ArrayList<Range.Bucket>(range.getBuckets());
|
||||
List<Range.Bucket> buckets = new ArrayList<>(range.getBuckets());
|
||||
|
||||
Range.Bucket bucket = buckets.get(0);
|
||||
assertThat((String) bucket.getKey(), equalTo("a long time ago"));
|
||||
|
@ -421,6 +421,7 @@ public class DateRangeIT extends ESIntegTestCase {
|
|||
assertThat(range.getName(), equalTo("range"));
|
||||
List<? extends Bucket> buckets = range.getBuckets();
|
||||
assertThat(buckets.size(), equalTo(3));
|
||||
assertThat(range.getProperty("_bucket_count"), equalTo(3));
|
||||
Object[] propertiesKeys = (Object[]) range.getProperty("_key");
|
||||
Object[] propertiesDocCounts = (Object[]) range.getProperty("_count");
|
||||
Object[] propertiesCounts = (Object[]) range.getProperty("sum.value");
|
||||
|
@ -855,7 +856,7 @@ public class DateRangeIT extends ESIntegTestCase {
|
|||
|
||||
Range dateRange = bucket.getAggregations().get("date_range");
|
||||
// TODO: use diamond once JI-9019884 is fixed
|
||||
List<Range.Bucket> buckets = new ArrayList<Range.Bucket>(dateRange.getBuckets());
|
||||
List<Range.Bucket> buckets = new ArrayList<>(dateRange.getBuckets());
|
||||
assertThat(dateRange, Matchers.notNullValue());
|
||||
assertThat(dateRange.getName(), equalTo("date_range"));
|
||||
assertThat(buckets.size(), is(1));
|
||||
|
|
|
@ -426,6 +426,7 @@ public class DoubleTermsIT extends AbstractTermsTestCase {
|
|||
assertThat(terms, notNullValue());
|
||||
assertThat(terms.getName(), equalTo("terms"));
|
||||
assertThat(terms.getBuckets().size(), equalTo(5));
|
||||
assertThat(terms.getProperty("_bucket_count"), equalTo(5));
|
||||
Object[] propertiesKeys = (Object[]) terms.getProperty("_key");
|
||||
Object[] propertiesDocCounts = (Object[]) terms.getProperty("_count");
|
||||
Object[] propertiesCounts = (Object[]) terms.getProperty("sum.value");
|
||||
|
|
|
@ -172,6 +172,7 @@ public class FiltersIT extends ESIntegTestCase {
|
|||
assertThat(filters.getName(), equalTo("tags"));
|
||||
|
||||
assertThat(filters.getBuckets().size(), equalTo(2));
|
||||
assertThat(filters.getProperty("_bucket_count"), equalTo(2));
|
||||
Object[] propertiesKeys = (Object[]) filters.getProperty("_key");
|
||||
Object[] propertiesDocCounts = (Object[]) filters.getProperty("_count");
|
||||
Object[] propertiesCounts = (Object[]) filters.getProperty("avg_value.value");
|
||||
|
@ -426,6 +427,7 @@ public class FiltersIT extends ESIntegTestCase {
|
|||
assertThat(filters.getName(), equalTo("tags"));
|
||||
|
||||
assertThat(filters.getBuckets().size(), equalTo(3));
|
||||
assertThat(filters.getProperty("_bucket_count"), equalTo(3));
|
||||
Object[] propertiesKeys = (Object[]) filters.getProperty("_key");
|
||||
Object[] propertiesDocCounts = (Object[]) filters.getProperty("_count");
|
||||
Object[] propertiesCounts = (Object[]) filters.getProperty("avg_value.value");
|
||||
|
|
|
@ -349,6 +349,7 @@ public class GeoDistanceIT extends ESIntegTestCase {
|
|||
assertThat(geoDist.getName(), equalTo("amsterdam_rings"));
|
||||
List<? extends Bucket> buckets = geoDist.getBuckets();
|
||||
assertThat(geoDist.getBuckets().size(), equalTo(3));
|
||||
assertThat(geoDist.getProperty("_bucket_count"), equalTo(3));
|
||||
Object[] propertiesKeys = (Object[]) geoDist.getProperty("_key");
|
||||
Object[] propertiesDocCounts = (Object[]) geoDist.getProperty("_count");
|
||||
Object[] propertiesCities = (Object[]) geoDist.getProperty("cities");
|
||||
|
@ -429,7 +430,7 @@ public class GeoDistanceIT extends ESIntegTestCase {
|
|||
|
||||
Range geoDistance = bucket.getAggregations().get("geo_dist");
|
||||
// TODO: use diamond once JI-9019884 is fixed
|
||||
List<Range.Bucket> buckets = new ArrayList<Range.Bucket>(geoDistance.getBuckets());
|
||||
List<Range.Bucket> buckets = new ArrayList<>(geoDistance.getBuckets());
|
||||
assertThat(geoDistance, Matchers.notNullValue());
|
||||
assertThat(geoDistance.getName(), equalTo("geo_dist"));
|
||||
assertThat(buckets.size(), is(1));
|
||||
|
|
|
@ -26,7 +26,6 @@ import org.elasticsearch.plugins.Plugin;
|
|||
import org.elasticsearch.script.MockScriptPlugin;
|
||||
import org.elasticsearch.script.Script;
|
||||
import org.elasticsearch.script.ScriptService.ScriptType;
|
||||
import org.elasticsearch.search.aggregations.AggregationTestScriptsPlugin;
|
||||
import org.elasticsearch.search.aggregations.bucket.filter.Filter;
|
||||
import org.elasticsearch.search.aggregations.bucket.histogram.ExtendedBounds;
|
||||
import org.elasticsearch.search.aggregations.bucket.histogram.Histogram;
|
||||
|
@ -253,7 +252,7 @@ public class HistogramIT extends ESIntegTestCase {
|
|||
assertThat(histo.getBuckets().size(), equalTo(numValueBuckets));
|
||||
|
||||
// TODO: use diamond once JI-9019884 is fixed
|
||||
List<Histogram.Bucket> buckets = new ArrayList<Histogram.Bucket>(histo.getBuckets());
|
||||
List<Histogram.Bucket> buckets = new ArrayList<>(histo.getBuckets());
|
||||
for (int i = 0; i < numValueBuckets; ++i) {
|
||||
Histogram.Bucket bucket = buckets.get(i);
|
||||
assertThat(bucket, notNullValue());
|
||||
|
@ -276,7 +275,7 @@ public class HistogramIT extends ESIntegTestCase {
|
|||
assertThat(histo.getBuckets().size(), equalTo(numValueBuckets));
|
||||
|
||||
// TODO: use diamond once JI-9019884 is fixed
|
||||
List<Histogram.Bucket> buckets = new ArrayList<Histogram.Bucket>(histo.getBuckets());
|
||||
List<Histogram.Bucket> buckets = new ArrayList<>(histo.getBuckets());
|
||||
for (int i = 0; i < numValueBuckets; ++i) {
|
||||
Histogram.Bucket bucket = buckets.get(numValueBuckets - i - 1);
|
||||
assertThat(bucket, notNullValue());
|
||||
|
@ -300,7 +299,7 @@ public class HistogramIT extends ESIntegTestCase {
|
|||
|
||||
LongHashSet buckets = new LongHashSet();
|
||||
// TODO: use diamond once JI-9019884 is fixed
|
||||
List<Histogram.Bucket> histoBuckets = new ArrayList<Histogram.Bucket>(histo.getBuckets());
|
||||
List<Histogram.Bucket> histoBuckets = new ArrayList<>(histo.getBuckets());
|
||||
long previousCount = Long.MIN_VALUE;
|
||||
for (int i = 0; i < numValueBuckets; ++i) {
|
||||
Histogram.Bucket bucket = histoBuckets.get(i);
|
||||
|
@ -329,7 +328,7 @@ public class HistogramIT extends ESIntegTestCase {
|
|||
|
||||
LongHashSet buckets = new LongHashSet();
|
||||
// TODO: use diamond once JI-9019884 is fixed
|
||||
List<Histogram.Bucket> histoBuckets = new ArrayList<Histogram.Bucket>(histo.getBuckets());
|
||||
List<Histogram.Bucket> histoBuckets = new ArrayList<>(histo.getBuckets());
|
||||
long previousCount = Long.MAX_VALUE;
|
||||
for (int i = 0; i < numValueBuckets; ++i) {
|
||||
Histogram.Bucket bucket = histoBuckets.get(i);
|
||||
|
@ -356,12 +355,13 @@ public class HistogramIT extends ESIntegTestCase {
|
|||
assertThat(histo, notNullValue());
|
||||
assertThat(histo.getName(), equalTo("histo"));
|
||||
assertThat(histo.getBuckets().size(), equalTo(numValueBuckets));
|
||||
assertThat(histo.getProperty("_bucket_count"), equalTo(numValueBuckets));
|
||||
Object[] propertiesKeys = (Object[]) histo.getProperty("_key");
|
||||
Object[] propertiesDocCounts = (Object[]) histo.getProperty("_count");
|
||||
Object[] propertiesCounts = (Object[]) histo.getProperty("sum.value");
|
||||
|
||||
// TODO: use diamond once JI-9019884 is fixed
|
||||
List<Histogram.Bucket> buckets = new ArrayList<Histogram.Bucket>(histo.getBuckets());
|
||||
List<Histogram.Bucket> buckets = new ArrayList<>(histo.getBuckets());
|
||||
for (int i = 0; i < numValueBuckets; ++i) {
|
||||
Histogram.Bucket bucket = buckets.get(i);
|
||||
assertThat(bucket, notNullValue());
|
||||
|
@ -404,7 +404,7 @@ public class HistogramIT extends ESIntegTestCase {
|
|||
LongHashSet visited = new LongHashSet();
|
||||
double previousSum = Double.NEGATIVE_INFINITY;
|
||||
// TODO: use diamond once JI-9019884 is fixed
|
||||
List<Histogram.Bucket> buckets = new ArrayList<Histogram.Bucket>(histo.getBuckets());
|
||||
List<Histogram.Bucket> buckets = new ArrayList<>(histo.getBuckets());
|
||||
for (int i = 0; i < numValueBuckets; ++i) {
|
||||
Histogram.Bucket bucket = buckets.get(i);
|
||||
assertThat(bucket, notNullValue());
|
||||
|
@ -448,7 +448,7 @@ public class HistogramIT extends ESIntegTestCase {
|
|||
LongHashSet visited = new LongHashSet();
|
||||
double previousSum = Double.POSITIVE_INFINITY;
|
||||
// TODO: use diamond once JI-9019884 is fixed
|
||||
List<Histogram.Bucket> buckets = new ArrayList<Histogram.Bucket>(histo.getBuckets());
|
||||
List<Histogram.Bucket> buckets = new ArrayList<>(histo.getBuckets());
|
||||
for (int i = 0; i < numValueBuckets; ++i) {
|
||||
Histogram.Bucket bucket = buckets.get(i);
|
||||
assertThat(bucket, notNullValue());
|
||||
|
@ -492,7 +492,7 @@ public class HistogramIT extends ESIntegTestCase {
|
|||
LongHashSet visited = new LongHashSet();
|
||||
double previousSum = Double.POSITIVE_INFINITY;
|
||||
// TODO: use diamond once JI-9019884 is fixed
|
||||
List<Histogram.Bucket> buckets = new ArrayList<Histogram.Bucket>(histo.getBuckets());
|
||||
List<Histogram.Bucket> buckets = new ArrayList<>(histo.getBuckets());
|
||||
for (int i = 0; i < numValueBuckets; ++i) {
|
||||
Histogram.Bucket bucket = buckets.get(i);
|
||||
assertThat(bucket, notNullValue());
|
||||
|
@ -538,7 +538,7 @@ public class HistogramIT extends ESIntegTestCase {
|
|||
LongHashSet visited = new LongHashSet();
|
||||
double prevMax = asc ? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY;
|
||||
// TODO: use diamond once JI-9019884 is fixed
|
||||
List<Histogram.Bucket> buckets = new ArrayList<Histogram.Bucket>(histo.getBuckets());
|
||||
List<Histogram.Bucket> buckets = new ArrayList<>(histo.getBuckets());
|
||||
for (int i = 0; i < numValueBuckets; ++i) {
|
||||
Histogram.Bucket bucket = buckets.get(i);
|
||||
assertThat(bucket, notNullValue());
|
||||
|
@ -625,7 +625,7 @@ public class HistogramIT extends ESIntegTestCase {
|
|||
assertThat(histo.getBuckets().size(), equalTo(numValuesBuckets));
|
||||
|
||||
// TODO: use diamond once JI-9019884 is fixed
|
||||
List<Histogram.Bucket> buckets = new ArrayList<Histogram.Bucket>(histo.getBuckets());
|
||||
List<Histogram.Bucket> buckets = new ArrayList<>(histo.getBuckets());
|
||||
for (int i = 0; i < numValuesBuckets; ++i) {
|
||||
Histogram.Bucket bucket = buckets.get(numValuesBuckets - i - 1);
|
||||
assertThat(bucket, notNullValue());
|
||||
|
|
|
@ -107,8 +107,7 @@ a metric embedded inside a sibling aggregation:
|
|||
=== Special Paths
|
||||
|
||||
Instead of pathing to a metric, `buckets_path` can use a special `"_count"` path. This instructs
|
||||
the pipeline aggregation to use the document count as it's input. For example, a moving average can be calculated on the document
|
||||
count of each bucket, instead of a specific metric:
|
||||
the pipeline aggregation to use the document count as it's input. For example, a moving average can be calculated on the document count of each bucket, instead of a specific metric:
|
||||
|
||||
[source,js]
|
||||
--------------------------------------------------
|
||||
|
@ -128,6 +127,44 @@ count of each bucket, instead of a specific metric:
|
|||
--------------------------------------------------
|
||||
<1> By using `_count` instead of a metric name, we can calculate the moving average of document counts in the histogram
|
||||
|
||||
The `buckets_path` can also use `"_bucket_count"` and path to a multi-bucket aggregation to use the number of buckets
|
||||
returned by that aggregation in the pipeline aggregation instead of a metric. for example a `bucket_selector` can be
|
||||
used here to filter out buckets which contain no buckets for an inner terms aggregation:
|
||||
|
||||
[source,js]
|
||||
--------------------------------------------------
|
||||
{
|
||||
"size": 0,
|
||||
"aggs": {
|
||||
"histo": {
|
||||
"date_histogram": {
|
||||
"field": "date",
|
||||
"interval": "day"
|
||||
},
|
||||
"aggs": {
|
||||
"categories": {
|
||||
"terms": {
|
||||
"field": "category"
|
||||
}
|
||||
},
|
||||
"min_bucket_selector": {
|
||||
"bucket_selector": {
|
||||
"buckets_path": {
|
||||
"count": "categories._bucket_count"
|
||||
},
|
||||
"script": {
|
||||
"inline": "count != 0"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
--------------------------------------------------
|
||||
<1> By using `_bucket_count` instead of a metric name, we can filter out `histo` buckets where they contain no buckets
|
||||
for the `categories` aggregation
|
||||
|
||||
[[dots-in-agg-names]]
|
||||
[float]
|
||||
=== Dealing with dots in agg names
|
||||
|
|
Loading…
Reference in New Issue