Skip to content

Commit 127649d

Browse files
committed
Aggregations: Added pre and post offset to histogram aggregation
Added preOffset and postOffset parameters to the API for the histogram aggregation which work in the same way as in the date histogram Closes #6605
1 parent f5d1e0a commit 127649d

File tree

11 files changed

+207
-128
lines changed

11 files changed

+207
-128
lines changed

src/main/java/org/elasticsearch/common/rounding/Rounding.java

+104-2
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,108 @@ public void writeTo(StreamOutput out) throws IOException {
128128
}
129129
}
130130

131+
public static class FactorRounding extends Rounding {
132+
133+
final static byte ID = 7;
134+
135+
private Rounding rounding;
136+
137+
private float factor;
138+
139+
FactorRounding() { // for serialization
140+
}
141+
142+
FactorRounding(Rounding rounding, float factor) {
143+
this.rounding = rounding;
144+
this.factor = factor;
145+
}
146+
147+
@Override
148+
public byte id() {
149+
return ID;
150+
}
151+
152+
@Override
153+
public long roundKey(long utcMillis) {
154+
return rounding.roundKey((long) (factor * utcMillis));
155+
}
156+
157+
@Override
158+
public long valueForKey(long key) {
159+
return rounding.valueForKey(key);
160+
}
161+
162+
@Override
163+
public long nextRoundingValue(long value) {
164+
return rounding.nextRoundingValue(value);
165+
}
166+
167+
@Override
168+
public void readFrom(StreamInput in) throws IOException {
169+
rounding = (TimeZoneRounding) Rounding.Streams.read(in);
170+
factor = in.readFloat();
171+
}
172+
173+
@Override
174+
public void writeTo(StreamOutput out) throws IOException {
175+
Rounding.Streams.write(rounding, out);
176+
out.writeFloat(factor);
177+
}
178+
}
179+
180+
public static class PrePostRounding extends Rounding {
181+
182+
final static byte ID = 8;
183+
184+
private Rounding rounding;
185+
186+
private long preOffset;
187+
private long postOffset;
188+
189+
PrePostRounding() { // for serialization
190+
}
191+
192+
public PrePostRounding(Rounding intervalRounding, long preOffset, long postOffset) {
193+
this.rounding = intervalRounding;
194+
this.preOffset = preOffset;
195+
this.postOffset = postOffset;
196+
}
197+
198+
@Override
199+
public byte id() {
200+
return ID;
201+
}
202+
203+
@Override
204+
public long roundKey(long value) {
205+
return rounding.roundKey(value + preOffset);
206+
}
207+
208+
@Override
209+
public long valueForKey(long key) {
210+
return postOffset + rounding.valueForKey(key);
211+
}
212+
213+
@Override
214+
public long nextRoundingValue(long value) {
215+
return postOffset + rounding.nextRoundingValue(value - postOffset);
216+
}
217+
218+
@Override
219+
public void readFrom(StreamInput in) throws IOException {
220+
rounding = Rounding.Streams.read(in);
221+
preOffset = in.readVLong();
222+
postOffset = in.readVLong();
223+
}
224+
225+
@Override
226+
public void writeTo(StreamOutput out) throws IOException {
227+
Rounding.Streams.write(rounding, out);
228+
out.writeVLong(preOffset);
229+
out.writeVLong(postOffset);
230+
}
231+
}
232+
131233
public static class Streams {
132234

133235
public static void write(Rounding rounding, StreamOutput out) throws IOException {
@@ -146,8 +248,8 @@ public static Rounding read(StreamInput in) throws IOException {
146248
case TimeZoneRounding.UTCIntervalTimeZoneRounding.ID: rounding = new TimeZoneRounding.UTCIntervalTimeZoneRounding(); break;
147249
case TimeZoneRounding.TimeIntervalTimeZoneRounding.ID: rounding = new TimeZoneRounding.TimeIntervalTimeZoneRounding(); break;
148250
case TimeZoneRounding.DayIntervalTimeZoneRounding.ID: rounding = new TimeZoneRounding.DayIntervalTimeZoneRounding(); break;
149-
case TimeZoneRounding.FactorTimeZoneRounding.ID: rounding = new TimeZoneRounding.FactorTimeZoneRounding(); break;
150-
case TimeZoneRounding.PrePostTimeZoneRounding.ID: rounding = new TimeZoneRounding.PrePostTimeZoneRounding(); break;
251+
case TimeZoneRounding.FactorRounding.ID: rounding = new FactorRounding(); break;
252+
case PrePostRounding.ID: rounding = new PrePostRounding(); break;
151253
default: throw new ElasticsearchException("unknown rounding id [" + id + "]");
152254
}
153255
rounding.readFrom(in);

src/main/java/org/elasticsearch/common/rounding/TimeZoneRounding.java

+4-106
Original file line numberDiff line numberDiff line change
@@ -94,8 +94,8 @@ public Builder factor(float factor) {
9494
return this;
9595
}
9696

97-
public TimeZoneRounding build() {
98-
TimeZoneRounding timeZoneRounding;
97+
public Rounding build() {
98+
Rounding timeZoneRounding;
9999
if (unit != null) {
100100
if (preTz.equals(DateTimeZone.UTC) && postTz.equals(DateTimeZone.UTC)) {
101101
timeZoneRounding = new UTCTimeZoneRoundingFloor(unit);
@@ -114,10 +114,10 @@ public TimeZoneRounding build() {
114114
}
115115
}
116116
if (preOffset != 0 || postOffset != 0) {
117-
timeZoneRounding = new PrePostTimeZoneRounding(timeZoneRounding, preOffset, postOffset);
117+
timeZoneRounding = new PrePostRounding(timeZoneRounding, preOffset, postOffset);
118118
}
119119
if (factor != 1.0f) {
120-
timeZoneRounding = new FactorTimeZoneRounding(timeZoneRounding, factor);
120+
timeZoneRounding = new FactorRounding(timeZoneRounding, factor);
121121
}
122122
return timeZoneRounding;
123123
}
@@ -439,106 +439,4 @@ public void writeTo(StreamOutput out) throws IOException {
439439
out.writeSharedString(postTz.getID());
440440
}
441441
}
442-
443-
static class FactorTimeZoneRounding extends TimeZoneRounding {
444-
445-
final static byte ID = 7;
446-
447-
private TimeZoneRounding timeZoneRounding;
448-
449-
private float factor;
450-
451-
FactorTimeZoneRounding() { // for serialization
452-
}
453-
454-
FactorTimeZoneRounding(TimeZoneRounding timeZoneRounding, float factor) {
455-
this.timeZoneRounding = timeZoneRounding;
456-
this.factor = factor;
457-
}
458-
459-
@Override
460-
public byte id() {
461-
return ID;
462-
}
463-
464-
@Override
465-
public long roundKey(long utcMillis) {
466-
return timeZoneRounding.roundKey((long) (factor * utcMillis));
467-
}
468-
469-
@Override
470-
public long valueForKey(long key) {
471-
return timeZoneRounding.valueForKey(key);
472-
}
473-
474-
@Override
475-
public long nextRoundingValue(long value) {
476-
return timeZoneRounding.nextRoundingValue(value);
477-
}
478-
479-
@Override
480-
public void readFrom(StreamInput in) throws IOException {
481-
timeZoneRounding = (TimeZoneRounding) Rounding.Streams.read(in);
482-
factor = in.readFloat();
483-
}
484-
485-
@Override
486-
public void writeTo(StreamOutput out) throws IOException {
487-
Rounding.Streams.write(timeZoneRounding, out);
488-
out.writeFloat(factor);
489-
}
490-
}
491-
492-
static class PrePostTimeZoneRounding extends TimeZoneRounding {
493-
494-
final static byte ID = 8;
495-
496-
private TimeZoneRounding timeZoneRounding;
497-
498-
private long preOffset;
499-
private long postOffset;
500-
501-
PrePostTimeZoneRounding() { // for serialization
502-
}
503-
504-
PrePostTimeZoneRounding(TimeZoneRounding timeZoneRounding, long preOffset, long postOffset) {
505-
this.timeZoneRounding = timeZoneRounding;
506-
this.preOffset = preOffset;
507-
this.postOffset = postOffset;
508-
}
509-
510-
@Override
511-
public byte id() {
512-
return ID;
513-
}
514-
515-
@Override
516-
public long roundKey(long utcMillis) {
517-
return timeZoneRounding.roundKey(utcMillis + preOffset);
518-
}
519-
520-
@Override
521-
public long valueForKey(long key) {
522-
return postOffset + timeZoneRounding.valueForKey(key);
523-
}
524-
525-
@Override
526-
public long nextRoundingValue(long value) {
527-
return postOffset + timeZoneRounding.nextRoundingValue(value - postOffset);
528-
}
529-
530-
@Override
531-
public void readFrom(StreamInput in) throws IOException {
532-
timeZoneRounding = (TimeZoneRounding) Rounding.Streams.read(in);
533-
preOffset = in.readVLong();
534-
postOffset = in.readVLong();
535-
}
536-
537-
@Override
538-
public void writeTo(StreamOutput out) throws IOException {
539-
Rounding.Streams.write(timeZoneRounding, out);
540-
out.writeVLong(preOffset);
541-
out.writeVLong(postOffset);
542-
}
543-
}
544442
}

src/main/java/org/elasticsearch/search/aggregations/bucket/histogram/DateHistogramParser.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import org.elasticsearch.common.ParseField;
2323
import org.elasticsearch.common.collect.MapBuilder;
2424
import org.elasticsearch.common.rounding.DateTimeUnit;
25+
import org.elasticsearch.common.rounding.Rounding;
2526
import org.elasticsearch.common.rounding.TimeZoneRounding;
2627
import org.elasticsearch.common.unit.TimeValue;
2728
import org.elasticsearch.common.xcontent.XContentParser;
@@ -192,7 +193,7 @@ public AggregatorFactory parse(String aggregationName, XContentParser parser, Se
192193
tzRoundingBuilder = TimeZoneRounding.builder(TimeValue.parseTimeValue(interval, null));
193194
}
194195

195-
TimeZoneRounding rounding = tzRoundingBuilder
196+
Rounding rounding = tzRoundingBuilder
196197
.preZone(preZone).postZone(postZone)
197198
.preZoneAdjustLargeInterval(preZoneAdjustLargeInterval)
198199
.preOffset(preOffset).postOffset(postOffset)

src/main/java/org/elasticsearch/search/aggregations/bucket/histogram/HistogramBuilder.java

+21
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ public class HistogramBuilder extends ValuesSourceAggregationBuilder<HistogramBu
3535
private Long minDocCount;
3636
private Long extendedBoundsMin;
3737
private Long extendedBoundsMax;
38+
private Long preOffset;
39+
private Long postOffset;
3840

3941
/**
4042
* Constructs a new histogram aggregation builder.
@@ -83,6 +85,16 @@ public HistogramBuilder extendedBounds(Long min, Long max) {
8385
extendedBoundsMax = max;
8486
return this;
8587
}
88+
89+
public HistogramBuilder preOffset(long preOffset) {
90+
this.preOffset = preOffset;
91+
return this;
92+
}
93+
94+
public HistogramBuilder postOffset(long postOffset) {
95+
this.postOffset = postOffset;
96+
return this;
97+
}
8698

8799
@Override
88100
protected XContentBuilder doInternalXContent(XContentBuilder builder, Params params) throws IOException {
@@ -96,6 +108,15 @@ protected XContentBuilder doInternalXContent(XContentBuilder builder, Params par
96108
order.toXContent(builder, params);
97109
}
98110

111+
if (preOffset != null) {
112+
builder.field("pre_offset", preOffset);
113+
}
114+
115+
if (postOffset != null) {
116+
builder.field("post_offset", postOffset);
117+
}
118+
119+
99120
if (minDocCount != null) {
100121
builder.field("min_doc_count", minDocCount);
101122
}

src/main/java/org/elasticsearch/search/aggregations/bucket/histogram/HistogramParser.java

+10
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@ public AggregatorFactory parse(String aggregationName, XContentParser parser, Se
5757
InternalOrder order = (InternalOrder) InternalOrder.KEY_ASC;
5858
long interval = -1;
5959
ExtendedBounds extendedBounds = null;
60+
long preOffset = 0;
61+
long postOffset = 0;
6062

6163
XContentParser.Token token;
6264
String currentFieldName = null;
@@ -72,6 +74,10 @@ public AggregatorFactory parse(String aggregationName, XContentParser parser, Se
7274
minDocCount = parser.longValue();
7375
} else if ("keyed".equals(currentFieldName)) {
7476
keyed = parser.booleanValue();
77+
} else if ("pre_offset".equals(currentFieldName) || "preOffset".equals(currentFieldName)) {
78+
preOffset = parser.longValue();
79+
} else if ("post_offset".equals(currentFieldName) || "postOffset".equals(currentFieldName)) {
80+
postOffset = parser.longValue();
7581
} else {
7682
throw new SearchParseException(context, "Unknown key for a " + token + " in aggregation [" + aggregationName + "]: [" + currentFieldName + "].");
7783
}
@@ -116,7 +122,11 @@ public AggregatorFactory parse(String aggregationName, XContentParser parser, Se
116122
if (interval < 0) {
117123
throw new SearchParseException(context, "Missing required field [interval] for histogram aggregation [" + aggregationName + "]");
118124
}
125+
119126
Rounding rounding = new Rounding.Interval(interval);
127+
if (preOffset != 0 || postOffset != 0) {
128+
rounding = new Rounding.PrePostRounding((Rounding.Interval) rounding, preOffset, postOffset);
129+
}
120130

121131
if (extendedBounds != null) {
122132
// with numeric histogram, we can process here and fail fast if the bounds are invalid

src/main/java/org/elasticsearch/search/facet/datehistogram/CountDateHistogramFacetExecutor.java

+5-5
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
import org.apache.lucene.index.SortedNumericDocValues;
2525
import org.elasticsearch.cache.recycler.CacheRecycler;
2626
import org.elasticsearch.common.recycler.Recycler;
27-
import org.elasticsearch.common.rounding.TimeZoneRounding;
27+
import org.elasticsearch.common.rounding.Rounding;
2828
import org.elasticsearch.index.fielddata.IndexNumericFieldData;
2929
import org.elasticsearch.search.facet.FacetExecutor;
3030
import org.elasticsearch.search.facet.InternalFacet;
@@ -38,13 +38,13 @@
3838
*/
3939
public class CountDateHistogramFacetExecutor extends FacetExecutor {
4040

41-
private final TimeZoneRounding tzRounding;
41+
private final Rounding tzRounding;
4242
private final IndexNumericFieldData indexFieldData;
4343
final DateHistogramFacet.ComparatorType comparatorType;
4444

4545
final Recycler.V<LongLongOpenHashMap> counts;
4646

47-
public CountDateHistogramFacetExecutor(IndexNumericFieldData indexFieldData, TimeZoneRounding tzRounding, DateHistogramFacet.ComparatorType comparatorType, CacheRecycler cacheRecycler) {
47+
public CountDateHistogramFacetExecutor(IndexNumericFieldData indexFieldData, Rounding tzRounding, DateHistogramFacet.ComparatorType comparatorType, CacheRecycler cacheRecycler) {
4848
this.comparatorType = comparatorType;
4949
this.indexFieldData = indexFieldData;
5050
this.tzRounding = tzRounding;
@@ -101,9 +101,9 @@ public void postCollection() {
101101
public static class DateHistogramProc extends LongFacetAggregatorBase {
102102

103103
private final LongLongOpenHashMap counts;
104-
private final TimeZoneRounding tzRounding;
104+
private final Rounding tzRounding;
105105

106-
public DateHistogramProc(LongLongOpenHashMap counts, TimeZoneRounding tzRounding) {
106+
public DateHistogramProc(LongLongOpenHashMap counts, Rounding tzRounding) {
107107
this.counts = counts;
108108
this.tzRounding = tzRounding;
109109
}

src/main/java/org/elasticsearch/search/facet/datehistogram/DateHistogramFacetParser.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import org.elasticsearch.common.component.AbstractComponent;
2525
import org.elasticsearch.common.inject.Inject;
2626
import org.elasticsearch.common.rounding.DateTimeUnit;
27+
import org.elasticsearch.common.rounding.Rounding;
2728
import org.elasticsearch.common.rounding.TimeZoneRounding;
2829
import org.elasticsearch.common.settings.Settings;
2930
import org.elasticsearch.common.unit.TimeValue;
@@ -179,7 +180,7 @@ public FacetExecutor parse(String facetName, XContentParser parser, SearchContex
179180
tzRoundingBuilder = TimeZoneRounding.builder(TimeValue.parseTimeValue(interval, null));
180181
}
181182

182-
TimeZoneRounding tzRounding = tzRoundingBuilder
183+
Rounding tzRounding = tzRoundingBuilder
183184
.preZone(preZone).postZone(postZone)
184185
.preZoneAdjustLargeInterval(preZoneAdjustLargeInterval)
185186
.preOffset(preOffset).postOffset(postOffset)

0 commit comments

Comments
 (0)