Skip to content

Commit 782ef13

Browse files
polyfractaluboness
authored andcommitted
Initial code dump
1 parent da680be commit 782ef13

19 files changed

+2534
-1
lines changed

config/logging.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# you can override this using by setting a system property, for example -Des.logger.level=DEBUG
2-
es.logger.level: INFO
2+
es.logger.level: DEBUG
33
rootLogger: ${es.logger.level}, console, file
44
logger:
55
# log action execution errors for easier debugging

src/main/java/org/elasticsearch/search/aggregations/AggregationBuilders.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
import org.elasticsearch.search.aggregations.metrics.avg.AvgBuilder;
3434
import org.elasticsearch.search.aggregations.metrics.max.MaxBuilder;
3535
import org.elasticsearch.search.aggregations.metrics.min.MinBuilder;
36+
import org.elasticsearch.search.aggregations.metrics.percentile.PercentileBuilder;
3637
import org.elasticsearch.search.aggregations.metrics.stats.StatsBuilder;
3738
import org.elasticsearch.search.aggregations.metrics.stats.extended.ExtendedStatsBuilder;
3839
import org.elasticsearch.search.aggregations.metrics.sum.SumBuilder;
@@ -121,4 +122,8 @@ public static IPv4RangeBuilder ipRange(String name) {
121122
public static TermsBuilder terms(String name) {
122123
return new TermsBuilder(name);
123124
}
125+
126+
public static PercentileBuilder percentile(String name) {
127+
return new PercentileBuilder(name);
128+
}
124129
}

src/main/java/org/elasticsearch/search/aggregations/AggregationModule.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
import org.elasticsearch.search.aggregations.metrics.avg.AvgParser;
3838
import org.elasticsearch.search.aggregations.metrics.max.MaxParser;
3939
import org.elasticsearch.search.aggregations.metrics.min.MinParser;
40+
import org.elasticsearch.search.aggregations.metrics.percentile.PercentileParser;
4041
import org.elasticsearch.search.aggregations.metrics.stats.StatsParser;
4142
import org.elasticsearch.search.aggregations.metrics.stats.extended.ExtendedStatsParser;
4243
import org.elasticsearch.search.aggregations.metrics.sum.SumParser;
@@ -59,6 +60,7 @@ public AggregationModule() {
5960
parsers.add(StatsParser.class);
6061
parsers.add(ExtendedStatsParser.class);
6162
parsers.add(ValueCountParser.class);
63+
parsers.add(PercentileParser.class);
6264

6365
parsers.add(GlobalParser.class);
6466
parsers.add(MissingParser.class);
Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
/*
2+
* Licensed to ElasticSearch and Shay Banon under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. ElasticSearch licenses this
6+
* file to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
package org.elasticsearch.search.aggregations.metrics.percentile;
21+
22+
import org.elasticsearch.common.io.stream.StreamInput;
23+
import org.elasticsearch.common.io.stream.StreamOutput;
24+
import org.elasticsearch.common.logging.ESLogger;
25+
import org.elasticsearch.common.logging.Loggers;
26+
import org.elasticsearch.common.xcontent.XContentBuilder;
27+
import org.elasticsearch.search.aggregations.AggregationStreams;
28+
import org.elasticsearch.search.aggregations.InternalAggregation;
29+
import org.elasticsearch.search.aggregations.metrics.MetricsAggregation;
30+
import org.elasticsearch.search.aggregations.metrics.percentile.providers.PercentileProvider;
31+
import org.elasticsearch.search.aggregations.support.numeric.ValueFormatterStreams;
32+
33+
import java.io.IOException;
34+
import java.util.List;
35+
36+
/**
37+
*
38+
*/
39+
public class InternalPercentile extends MetricsAggregation.MultiValue implements Percentile {
40+
41+
public final static Type TYPE = new Type("percentile");
42+
private static final ESLogger log= Loggers.getLogger(InternalPercentile.class);
43+
44+
public static enum EXECUTION_HINT {
45+
FRUGAL, QDIGEST, TDIGEST
46+
}
47+
48+
public final static AggregationStreams.Stream STREAM = new AggregationStreams.Stream() {
49+
@Override
50+
public InternalPercentile readResult(StreamInput in) throws IOException {
51+
InternalPercentile result = new InternalPercentile();
52+
result.readFrom(in);
53+
return result;
54+
}
55+
};
56+
57+
public static void registerStreams() {
58+
AggregationStreams.registerStream(STREAM, TYPE.stream());
59+
}
60+
61+
private PercentileProvider quantile;
62+
63+
InternalPercentile() {} // for serialization
64+
65+
public InternalPercentile(String name, PercentileProvider quantile) {
66+
super(name);
67+
this.quantile = quantile;
68+
}
69+
70+
@Override
71+
public double value(String name) {
72+
if ("min".equals(name)) {
73+
return 0;
74+
} else {
75+
throw new IllegalArgumentException("Unknown value [" + name + "] in percentile aggregation");
76+
}
77+
}
78+
79+
public double getValue(int index) {
80+
return quantile.getEstimate(index);
81+
}
82+
83+
@Override
84+
public Type type() {
85+
return TYPE;
86+
}
87+
88+
@Override
89+
public InternalPercentile reduce(ReduceContext reduceContext) {
90+
List<InternalAggregation> aggregations = reduceContext.aggregations();
91+
if (aggregations.size() == 1) {
92+
return (InternalPercentile) aggregations.get(0);
93+
}
94+
InternalPercentile reduced = null;
95+
int expectedMerges = aggregations.size();
96+
97+
for (InternalAggregation aggregation : aggregations) {
98+
if (reduced == null) {
99+
reduced = (InternalPercentile) aggregation;
100+
} else {
101+
reduced.quantile = reduced.quantile.merge(((InternalPercentile) aggregation).quantile, expectedMerges);
102+
}
103+
}
104+
105+
return reduced;
106+
}
107+
108+
@Override
109+
public void readFrom(StreamInput in) throws IOException {
110+
name = in.readString();
111+
valueFormatter = ValueFormatterStreams.readOptional(in);
112+
quantile.readFrom(in);
113+
}
114+
115+
@Override
116+
public void writeTo(StreamOutput out) throws IOException {
117+
out.writeString(name);
118+
ValueFormatterStreams.writeOptional(valueFormatter, out);
119+
quantile.writeTo(out);
120+
}
121+
122+
@Override
123+
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
124+
double intervals[] = quantile.getPercentiles();
125+
126+
127+
builder.startObject(name);
128+
builder.startObject("quantiles");
129+
130+
for(int i = 0; i < intervals.length; ++i) {
131+
132+
builder.field(String.valueOf(intervals[i]), getValue(i));
133+
134+
if (valueFormatter != null) {
135+
builder.field(String.valueOf(intervals[i]) + "_as_string", valueFormatter.format(getValue(i)));
136+
}
137+
138+
}
139+
builder.endObject();
140+
builder.endObject();
141+
return builder;
142+
}
143+
144+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/*
2+
* Licensed to ElasticSearch and Shay Banon under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. ElasticSearch licenses this
6+
* file to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
package org.elasticsearch.search.aggregations.metrics.percentile;
21+
22+
import org.elasticsearch.search.aggregations.Aggregation;
23+
import org.elasticsearch.search.aggregations.metrics.percentile.providers.PercentileProvider;
24+
25+
/**
26+
*
27+
*/
28+
public interface Percentile extends Aggregation {
29+
double getValue(int index);
30+
}
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
/*
2+
* Licensed to ElasticSearch and Shay Banon under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. ElasticSearch licenses this
6+
* file to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
package org.elasticsearch.search.aggregations.metrics.percentile;
21+
22+
import org.elasticsearch.common.util.BigArrays;
23+
import org.elasticsearch.common.util.ObjectArray;
24+
import org.elasticsearch.index.fielddata.DoubleValues;
25+
import org.elasticsearch.search.aggregations.Aggregator;
26+
import org.elasticsearch.search.aggregations.AggregatorFactories;
27+
import org.elasticsearch.search.aggregations.InternalAggregation;
28+
import org.elasticsearch.search.aggregations.metrics.percentile.providers.FrugalProvider;
29+
import org.elasticsearch.search.aggregations.metrics.percentile.providers.PercentileProvider;
30+
import org.elasticsearch.search.aggregations.metrics.percentile.providers.QDigestProvider;
31+
import org.elasticsearch.search.aggregations.metrics.percentile.providers.TDigestProvider;
32+
import org.elasticsearch.search.aggregations.support.AggregationContext;
33+
import org.elasticsearch.search.aggregations.support.ValueSourceAggregatorFactory;
34+
import org.elasticsearch.search.aggregations.support.ValuesSourceConfig;
35+
import org.elasticsearch.search.aggregations.support.numeric.NumericValuesSource;
36+
37+
import java.io.IOException;
38+
39+
/**
40+
*
41+
*/
42+
public class PercentileAggregator extends Aggregator {
43+
44+
private final NumericValuesSource valuesSource;
45+
46+
private ObjectArray<PercentileProvider> percentiles;
47+
private PercentileProvider.Factory percentileFactory;
48+
49+
50+
public PercentileAggregator(String name, long estimatedBucketsCount, NumericValuesSource valuesSource, AggregationContext context, Aggregator parent, PercentileProvider.Factory percentileFactory) {
51+
super(name, BucketAggregationMode.MULTI_BUCKETS, AggregatorFactories.EMPTY, estimatedBucketsCount, context, parent);
52+
this.valuesSource = valuesSource;
53+
this.percentileFactory = percentileFactory;
54+
if (valuesSource != null) {
55+
final long initialSize = estimatedBucketsCount < 2 ? 1 : estimatedBucketsCount;
56+
percentiles = BigArrays.newObjectArray(initialSize);
57+
for (long i = 0; i < initialSize; ++i) {
58+
percentiles.set(i, this.percentileFactory.create());
59+
}
60+
}
61+
}
62+
63+
@Override
64+
public boolean shouldCollect() {
65+
return valuesSource != null;
66+
}
67+
68+
@Override
69+
public void collect(int doc, long owningBucketOrdinal) throws IOException {
70+
assert valuesSource != null : "if value source is null, collect should never be called";
71+
72+
DoubleValues values = valuesSource.doubleValues();
73+
if (values == null) {
74+
return;
75+
}
76+
77+
if (owningBucketOrdinal >= percentiles.size()) {
78+
long from = percentiles.size();
79+
percentiles = BigArrays.grow(percentiles, owningBucketOrdinal + 1);
80+
for (long i = from; i < percentiles.size(); ++i) {
81+
percentiles.set(i, this.percentileFactory.create());
82+
}
83+
}
84+
85+
final int valueCount = values.setDocument(doc);
86+
PercentileProvider percentile = percentiles.get(owningBucketOrdinal);
87+
for (int i = 0; i < valueCount; i++) {
88+
percentile.offer(values.nextValue());
89+
}
90+
91+
percentiles.set(owningBucketOrdinal, percentile);
92+
}
93+
94+
@Override
95+
public InternalAggregation buildAggregation(long owningBucketOrdinal) {
96+
if (valuesSource == null || owningBucketOrdinal >= percentiles.size()) {
97+
return new InternalPercentile(name, percentileFactory.create());
98+
}
99+
return new InternalPercentile(name, percentiles.get(owningBucketOrdinal));
100+
}
101+
102+
@Override
103+
public InternalAggregation buildEmptyAggregation() {
104+
return new InternalPercentile(name, percentileFactory.create());
105+
}
106+
107+
public static class Factory extends ValueSourceAggregatorFactory.LeafOnly<NumericValuesSource> {
108+
109+
private final PercentileProvider.Factory percentileFactory;
110+
111+
public Factory(String name, String type, ValuesSourceConfig<NumericValuesSource> valuesSourceConfig, InternalPercentile.EXECUTION_HINT execution_hint, double[] percentiles) {
112+
super(name, type, valuesSourceConfig);
113+
114+
if (execution_hint == InternalPercentile.EXECUTION_HINT.QDIGEST) {
115+
this.percentileFactory = new QDigestProvider.Factory(percentiles);
116+
} else if (execution_hint == InternalPercentile.EXECUTION_HINT.FRUGAL) {
117+
this.percentileFactory = new FrugalProvider.Factory(percentiles);
118+
} else if (execution_hint == InternalPercentile.EXECUTION_HINT.TDIGEST) {
119+
this.percentileFactory = new TDigestProvider.Factory(percentiles);
120+
} else {
121+
this.percentileFactory = new TDigestProvider.Factory(percentiles);
122+
}
123+
}
124+
125+
@Override
126+
protected Aggregator createUnmapped(AggregationContext aggregationContext, Aggregator parent) {
127+
return new PercentileAggregator(name, 0, null, aggregationContext, parent, percentileFactory);
128+
}
129+
130+
@Override
131+
protected Aggregator create(NumericValuesSource valuesSource, long expectedBucketsCount, AggregationContext aggregationContext, Aggregator parent) {
132+
return new PercentileAggregator(name, expectedBucketsCount, valuesSource, aggregationContext, parent, percentileFactory);
133+
}
134+
}
135+
136+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package org.elasticsearch.search.aggregations.metrics.percentile;
2+
3+
import org.elasticsearch.search.aggregations.metrics.ValuesSourceMetricsAggregationBuilder;
4+
5+
/**
6+
*
7+
*/
8+
public class PercentileBuilder extends ValuesSourceMetricsAggregationBuilder<PercentileBuilder> {
9+
10+
public PercentileBuilder(String name) {
11+
super(name, InternalPercentile.TYPE.name());
12+
}
13+
}

0 commit comments

Comments
 (0)