Skip to content

Commit 5ca2e54

Browse files
author
Paul Sanwald
authored
Add interval response parameter to AutoDateInterval histogram (#33254) (#33437)
Adds the interval used to the aggregation response.
1 parent 7cb250a commit 5ca2e54

File tree

6 files changed

+74
-28
lines changed

6 files changed

+74
-28
lines changed

docs/reference/aggregations/bucket/autodatehistogram-aggregation.asciidoc

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,8 @@ Response:
8181
"key": 1425168000000,
8282
"doc_count": 2
8383
}
84-
]
84+
],
85+
"interval": "1M"
8586
}
8687
}
8788
}
@@ -174,7 +175,8 @@ starting at midnight UTC on 1 October 2015:
174175
"key": 1443664800000,
175176
"doc_count": 1
176177
}
177-
]
178+
],
179+
"interval": "1h"
178180
}
179181
}
180182
}
@@ -229,7 +231,8 @@ the specified time zone.
229231
"key": 1443664800000,
230232
"doc_count": 1
231233
}
232-
]
234+
],
235+
"interval": "1h"
233236
}
234237
}
235238
}

server/src/main/java/org/elasticsearch/search/aggregations/bucket/histogram/AutoDateHistogramAggregationBuilder.java

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -78,17 +78,17 @@ public class AutoDateHistogramAggregationBuilder
7878
static RoundingInfo[] buildRoundings(DateTimeZone timeZone) {
7979
RoundingInfo[] roundings = new RoundingInfo[6];
8080
roundings[0] = new RoundingInfo(createRounding(DateTimeUnit.SECOND_OF_MINUTE, timeZone),
81-
1000L, 1, 5, 10, 30);
81+
1000L, "s" , 1, 5, 10, 30);
8282
roundings[1] = new RoundingInfo(createRounding(DateTimeUnit.MINUTES_OF_HOUR, timeZone),
83-
60 * 1000L, 1, 5, 10, 30);
83+
60 * 1000L, "m", 1, 5, 10, 30);
8484
roundings[2] = new RoundingInfo(createRounding(DateTimeUnit.HOUR_OF_DAY, timeZone),
85-
60 * 60 * 1000L, 1, 3, 12);
85+
60 * 60 * 1000L, "h", 1, 3, 12);
8686
roundings[3] = new RoundingInfo(createRounding(DateTimeUnit.DAY_OF_MONTH, timeZone),
87-
24 * 60 * 60 * 1000L, 1, 7);
87+
24 * 60 * 60 * 1000L, "d", 1, 7);
8888
roundings[4] = new RoundingInfo(createRounding(DateTimeUnit.MONTH_OF_YEAR, timeZone),
89-
30 * 24 * 60 * 60 * 1000L, 1, 3);
89+
30 * 24 * 60 * 60 * 1000L, "M", 1, 3);
9090
roundings[5] = new RoundingInfo(createRounding(DateTimeUnit.YEAR_OF_CENTURY, timeZone),
91-
365 * 24 * 60 * 60 * 1000L, 1, 5, 10, 20, 50, 100);
91+
365 * 24 * 60 * 60 * 1000L, "y", 1, 5, 10, 20, 50, 100);
9292
return roundings;
9393
}
9494

@@ -200,24 +200,28 @@ public static class RoundingInfo implements Writeable {
200200
final Rounding rounding;
201201
final int[] innerIntervals;
202202
final long roughEstimateDurationMillis;
203+
final String unitAbbreviation;
203204

204-
public RoundingInfo(Rounding rounding, long roughEstimateDurationMillis, int... innerIntervals) {
205+
public RoundingInfo(Rounding rounding, long roughEstimateDurationMillis, String unitAbbreviation, int... innerIntervals) {
205206
this.rounding = rounding;
206207
this.roughEstimateDurationMillis = roughEstimateDurationMillis;
208+
this.unitAbbreviation = unitAbbreviation;
207209
this.innerIntervals = innerIntervals;
208210
}
209211

210212
public RoundingInfo(StreamInput in) throws IOException {
211213
rounding = Rounding.Streams.read(in);
212214
roughEstimateDurationMillis = in.readVLong();
213215
innerIntervals = in.readIntArray();
216+
unitAbbreviation = in.readString();
214217
}
215218

216219
@Override
217220
public void writeTo(StreamOutput out) throws IOException {
218221
Rounding.Streams.write(rounding, out);
219222
out.writeVLong(roughEstimateDurationMillis);
220223
out.writeIntArray(innerIntervals);
224+
out.writeString(unitAbbreviation);
221225
}
222226

223227
public int getMaximumInnerInterval() {

server/src/main/java/org/elasticsearch/search/aggregations/bucket/histogram/AutoDateHistogramAggregator.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -181,15 +181,16 @@ public InternalAggregation buildAggregation(long owningBucketOrdinal) throws IOE
181181
InternalAutoDateHistogram.BucketInfo emptyBucketInfo = new InternalAutoDateHistogram.BucketInfo(roundingInfos, roundingIdx,
182182
buildEmptySubAggregations());
183183

184-
return new InternalAutoDateHistogram(name, buckets, targetBuckets, emptyBucketInfo, formatter, pipelineAggregators(), metaData());
184+
return new InternalAutoDateHistogram(name, buckets, targetBuckets, emptyBucketInfo,
185+
formatter, pipelineAggregators(), metaData(), 1);
185186
}
186187

187188
@Override
188189
public InternalAggregation buildEmptyAggregation() {
189190
InternalAutoDateHistogram.BucketInfo emptyBucketInfo = new InternalAutoDateHistogram.BucketInfo(roundingInfos, roundingIdx,
190191
buildEmptySubAggregations());
191192
return new InternalAutoDateHistogram(name, Collections.emptyList(), targetBuckets, emptyBucketInfo, formatter,
192-
pipelineAggregators(), metaData());
193+
pipelineAggregators(), metaData(), 1);
193194
}
194195

195196
@Override

server/src/main/java/org/elasticsearch/search/aggregations/bucket/histogram/InternalAutoDateHistogram.java

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -208,15 +208,16 @@ public int hashCode() {
208208
private final DocValueFormat format;
209209
private final BucketInfo bucketInfo;
210210
private final int targetBuckets;
211-
211+
private long bucketInnerInterval;
212212

213213
InternalAutoDateHistogram(String name, List<Bucket> buckets, int targetBuckets, BucketInfo emptyBucketInfo, DocValueFormat formatter,
214-
List<PipelineAggregator> pipelineAggregators, Map<String, Object> metaData) {
214+
List<PipelineAggregator> pipelineAggregators, Map<String, Object> metaData, long bucketInnerInterval) {
215215
super(name, pipelineAggregators, metaData);
216216
this.buckets = buckets;
217217
this.bucketInfo = emptyBucketInfo;
218218
this.format = formatter;
219219
this.targetBuckets = targetBuckets;
220+
this.bucketInnerInterval = bucketInnerInterval;
220221
}
221222

222223
/**
@@ -238,6 +239,13 @@ protected void doWriteTo(StreamOutput out) throws IOException {
238239
out.writeVInt(targetBuckets);
239240
}
240241

242+
public DateHistogramInterval getInterval() {
243+
244+
RoundingInfo roundingInfo = this.bucketInfo.roundingInfos[this.bucketInfo.roundingIdx];
245+
String unitAbbreviation = roundingInfo.unitAbbreviation;
246+
return new DateHistogramInterval(Long.toString(bucketInnerInterval) + unitAbbreviation);
247+
}
248+
241249
@Override
242250
public String getWriteableName() {
243251
return AutoDateHistogramAggregationBuilder.NAME;
@@ -262,7 +270,7 @@ public BucketInfo getBucketInfo() {
262270

263271
@Override
264272
public InternalAutoDateHistogram create(List<Bucket> buckets) {
265-
return new InternalAutoDateHistogram(name, buckets, targetBuckets, bucketInfo, format, pipelineAggregators(), metaData);
273+
return new InternalAutoDateHistogram(name, buckets, targetBuckets, bucketInfo, format, pipelineAggregators(), metaData, 1);
266274
}
267275

268276
@Override
@@ -279,7 +287,6 @@ private static class IteratorAndCurrent {
279287
this.iterator = iterator;
280288
current = iterator.next();
281289
}
282-
283290
}
284291

285292
/**
@@ -365,7 +372,7 @@ private BucketReduceResult mergeBucketsIfNeeded(List<Bucket> reducedBuckets, int
365372
reduceRoundingInfo = bucketInfo.roundingInfos[reduceRoundingIdx];
366373
reducedBuckets = mergeBuckets(reducedBuckets, reduceRoundingInfo.rounding, reduceContext);
367374
}
368-
return new BucketReduceResult(reducedBuckets, reduceRoundingInfo, reduceRoundingIdx);
375+
return new BucketReduceResult(reducedBuckets, reduceRoundingInfo, reduceRoundingIdx, 1);
369376
}
370377

371378
private List<Bucket> mergeBuckets(List<Bucket> reducedBuckets, Rounding reduceRounding, ReduceContext reduceContext) {
@@ -403,12 +410,13 @@ private static class BucketReduceResult {
403410
List<Bucket> buckets;
404411
RoundingInfo roundingInfo;
405412
int roundingIdx;
413+
long innerInterval;
406414

407-
BucketReduceResult(List<Bucket> buckets, RoundingInfo roundingInfo, int roundingIdx) {
415+
BucketReduceResult(List<Bucket> buckets, RoundingInfo roundingInfo, int roundingIdx, long innerInterval) {
408416
this.buckets = buckets;
409417
this.roundingInfo = roundingInfo;
410418
this.roundingIdx = roundingIdx;
411-
419+
this.innerInterval = innerInterval;
412420
}
413421
}
414422

@@ -444,7 +452,7 @@ private BucketReduceResult addEmptyBuckets(BucketReduceResult currentResult, Red
444452
}
445453
lastBucket = iter.next();
446454
}
447-
return new BucketReduceResult(list, roundingInfo, roundingIdx);
455+
return new BucketReduceResult(list, roundingInfo, roundingIdx, currentResult.innerInterval);
448456
}
449457

450458
static int getAppropriateRounding(long minKey, long maxKey, int roundingIdx,
@@ -507,7 +515,7 @@ public InternalAggregation doReduce(List<InternalAggregation> aggregations, Redu
507515
this.bucketInfo.emptySubAggregations);
508516

509517
return new InternalAutoDateHistogram(getName(), reducedBucketsResult.buckets, targetBuckets, bucketInfo, format,
510-
pipelineAggregators(), getMetaData());
518+
pipelineAggregators(), getMetaData(), reducedBucketsResult.innerInterval);
511519
}
512520

513521
private BucketReduceResult maybeMergeConsecutiveBuckets(BucketReduceResult reducedBucketsResult,
@@ -547,7 +555,7 @@ private BucketReduceResult mergeConsecutiveBuckets(List<Bucket> reducedBuckets,
547555
reduceContext.consumeBucketsAndMaybeBreak(1);
548556
mergedBuckets.add(sameKeyedBuckets.get(0).reduce(sameKeyedBuckets, roundingInfo.rounding, reduceContext));
549557
}
550-
return new BucketReduceResult(mergedBuckets, roundingInfo, roundingIdx);
558+
return new BucketReduceResult(mergedBuckets, roundingInfo, roundingIdx, mergeInterval);
551559
}
552560

553561
@Override
@@ -557,6 +565,7 @@ public XContentBuilder doXContentBody(XContentBuilder builder, Params params) th
557565
bucket.toXContent(builder, params);
558566
}
559567
builder.endArray();
568+
builder.field("interval", getInterval().toString());
560569
return builder;
561570
}
562571

@@ -580,7 +589,7 @@ public InternalAggregation createAggregation(List<MultiBucketsAggregation.Bucket
580589
buckets2.add((Bucket) b);
581590
}
582591
buckets2 = Collections.unmodifiableList(buckets2);
583-
return new InternalAutoDateHistogram(name, buckets2, targetBuckets, bucketInfo, format, pipelineAggregators(), getMetaData());
592+
return new InternalAutoDateHistogram(name, buckets2, targetBuckets, bucketInfo, format, pipelineAggregators(), getMetaData(), 1);
584593
}
585594

586595
@Override

server/src/main/java/org/elasticsearch/search/aggregations/bucket/histogram/ParsedAutoDateHistogram.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
package org.elasticsearch.search.aggregations.bucket.histogram;
2121

22+
import org.elasticsearch.common.ParseField;
2223
import org.elasticsearch.common.xcontent.ObjectParser;
2324
import org.elasticsearch.common.xcontent.XContentBuilder;
2425
import org.elasticsearch.common.xcontent.XContentParser;
@@ -36,6 +37,16 @@ public String getType() {
3637
return AutoDateHistogramAggregationBuilder.NAME;
3738
}
3839

40+
private String interval;
41+
42+
public String getInterval() {
43+
return interval;
44+
}
45+
46+
public void setInterval(String interval) {
47+
this.interval = interval;
48+
}
49+
3950
@Override
4051
public List<? extends Histogram.Bucket> getBuckets() {
4152
return buckets;
@@ -47,6 +58,8 @@ public List<? extends Histogram.Bucket> getBuckets() {
4758
declareMultiBucketAggregationFields(PARSER,
4859
parser -> ParsedBucket.fromXContent(parser, false),
4960
parser -> ParsedBucket.fromXContent(parser, true));
61+
PARSER.declareString((parsed, value) -> parsed.interval = value,
62+
new ParseField("interval"));
5063
}
5164

5265
public static ParsedAutoDateHistogram fromXContent(XContentParser parser, String name) throws IOException {
@@ -55,6 +68,14 @@ public static ParsedAutoDateHistogram fromXContent(XContentParser parser, String
5568
return aggregation;
5669
}
5770

71+
@Override
72+
protected XContentBuilder doXContentBody(XContentBuilder builder, Params params) throws IOException {
73+
builder = super.doXContentBody(builder, params);
74+
builder.field("interval", getInterval());
75+
return builder;
76+
}
77+
78+
5879
public static class ParsedBucket extends ParsedMultiBucketAggregation.ParsedBucket implements Histogram.Bucket {
5980

6081
private Long key;

server/src/test/java/org/elasticsearch/search/aggregations/bucket/histogram/InternalAutoDateHistogramTests.java

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ protected InternalAutoDateHistogram createTestInstance(String name,
8080
}
8181
InternalAggregations subAggregations = new InternalAggregations(Collections.emptyList());
8282
BucketInfo bucketInfo = new BucketInfo(roundingInfos, randomIntBetween(0, roundingInfos.length - 1), subAggregations);
83-
return new InternalAutoDateHistogram(name, buckets, targetBuckets, bucketInfo, format, pipelineAggregators, metaData);
83+
return new InternalAutoDateHistogram(name, buckets, targetBuckets, bucketInfo, format, pipelineAggregators, metaData, 1);
8484
}
8585

8686
/*
@@ -94,11 +94,11 @@ public void testGetAppropriateRoundingUsesCorrectIntervals() {
9494
// an innerInterval that is quite large, such that targetBuckets * roundings[i].getMaximumInnerInterval()
9595
// will be larger than the estimate.
9696
roundings[0] = new RoundingInfo(createRounding(DateTimeUnit.SECOND_OF_MINUTE, timeZone),
97-
1000L, 1000);
97+
1000L, "s", 1000);
9898
roundings[1] = new RoundingInfo(createRounding(DateTimeUnit.MINUTES_OF_HOUR, timeZone),
99-
60 * 1000L, 1, 5, 10, 30);
99+
60 * 1000L, "m", 1, 5, 10, 30);
100100
roundings[2] = new RoundingInfo(createRounding(DateTimeUnit.HOUR_OF_DAY, timeZone),
101-
60 * 60 * 1000L, 1, 3, 12);
101+
60 * 60 * 1000L, "h", 1, 3, 12);
102102

103103
OffsetDateTime timestamp = Instant.parse("2018-01-01T00:00:01.000Z").atOffset(ZoneOffset.UTC);
104104
// We want to pass a roundingIdx of zero, because in order to reproduce this bug, we need the function
@@ -198,6 +198,14 @@ protected void assertReduced(InternalAutoDateHistogram reduced, List<InternalAut
198198
(key, oldValue) -> (oldValue == null ? 0 : oldValue) + bucket.getDocCount());
199199
}
200200
assertEquals(expectedCounts, actualCounts);
201+
202+
DateHistogramInterval expectedInterval;
203+
if (reduced.getBuckets().size() == 1) {
204+
expectedInterval = reduced.getInterval();
205+
} else {
206+
expectedInterval = new DateHistogramInterval(innerIntervalToUse+roundingInfo.unitAbbreviation);
207+
}
208+
assertThat(reduced.getInterval(), equalTo(expectedInterval));
201209
}
202210

203211
private int getBucketCount(long lowest, long highest, RoundingInfo roundingInfo, long intervalInMillis) {
@@ -252,6 +260,6 @@ protected InternalAutoDateHistogram mutateInstance(InternalAutoDateHistogram ins
252260
default:
253261
throw new AssertionError("Illegal randomisation branch");
254262
}
255-
return new InternalAutoDateHistogram(name, buckets, targetBuckets, bucketInfo, format, pipelineAggregators, metaData);
263+
return new InternalAutoDateHistogram(name, buckets, targetBuckets, bucketInfo, format, pipelineAggregators, metaData, 1);
256264
}
257265
}

0 commit comments

Comments
 (0)