Skip to content

Commit 0299689

Browse files
committed
checkpoint
1 parent d7ae6de commit 0299689

File tree

6 files changed

+518
-0
lines changed

6 files changed

+518
-0
lines changed

x-pack/plugin/analytics/src/main/java/org/elasticsearch/xpack/analytics/AnalyticsPlugin.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
import org.elasticsearch.plugins.ActionPlugin;
1212
import org.elasticsearch.plugins.Plugin;
1313
import org.elasticsearch.plugins.SearchPlugin;
14+
import org.elasticsearch.xpack.analytics.metricselector.InternalMetricSelector;
15+
import org.elasticsearch.xpack.analytics.metricselector.MetricSelectorAggregationBuilder;
1416
import org.elasticsearch.xpack.core.XPackPlugin;
1517
import org.elasticsearch.xpack.core.action.XPackInfoFeatureAction;
1618
import org.elasticsearch.xpack.core.action.XPackUsageFeatureAction;
@@ -52,4 +54,14 @@ public List<PipelineAggregationSpec> getPipelineAggregations() {
5254
new ActionHandler<>(XPackInfoFeatureAction.ANALYTICS, AnalyticsInfoTransportAction.class),
5355
new ActionHandler<>(AnalyticsStatsAction.INSTANCE, TransportAnalyticsStatsAction.class));
5456
}
57+
58+
@Override
59+
public List<AggregationSpec> getAggregations() {
60+
return singletonList(
61+
new AggregationSpec(
62+
MetricSelectorAggregationBuilder.NAME,
63+
MetricSelectorAggregationBuilder::new,
64+
MetricSelectorAggregationBuilder::parse).addResultReader(InternalMetricSelector::new)
65+
);
66+
}
5567
}
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License;
4+
* you may not use this file except in compliance with the Elastic License.
5+
*/
6+
package org.elasticsearch.xpack.analytics.metricselector;
7+
8+
import org.elasticsearch.common.ParseField;
9+
import org.elasticsearch.common.io.stream.StreamInput;
10+
import org.elasticsearch.common.io.stream.StreamOutput;
11+
import org.elasticsearch.common.xcontent.XContentBuilder;
12+
import org.elasticsearch.search.DocValueFormat;
13+
import org.elasticsearch.search.aggregations.InternalAggregation;
14+
import org.elasticsearch.search.aggregations.metrics.InternalNumericMetricsAggregation;
15+
import org.elasticsearch.search.aggregations.metrics.WeightedAvg;
16+
import org.elasticsearch.search.aggregations.pipeline.PipelineAggregator;
17+
18+
import java.io.IOException;
19+
import java.util.List;
20+
import java.util.Map;
21+
import java.util.Objects;
22+
23+
public class InternalMetricSelector extends InternalNumericMetricsAggregation.SingleValue implements WeightedAvg {
24+
private final double value;
25+
private final double sort;
26+
private final SelectionCriteria selectionCriteria;
27+
28+
public static final ParseField SORT_FIELD = new ParseField("sort");
29+
public static final ParseField SORT_FIELD_AS_STRING = new ParseField("sort_as_string");
30+
31+
InternalMetricSelector(String name, double value, double sort, SelectionCriteria selectionCriteria,
32+
DocValueFormat format, List<PipelineAggregator> pipelineAggregators,
33+
Map<String, Object> metaData) {
34+
super(name, pipelineAggregators, metaData);
35+
this.value = value;
36+
this.sort = sort;
37+
this.format = format;
38+
this.selectionCriteria = selectionCriteria;
39+
}
40+
41+
/**
42+
* Read from a stream.
43+
*/
44+
public InternalMetricSelector(StreamInput in) throws IOException {
45+
super(in);
46+
format = in.readNamedWriteable(DocValueFormat.class);
47+
value = in.readDouble();
48+
sort = in.readDouble();
49+
selectionCriteria = SelectionCriteria.fromStream(in);
50+
}
51+
52+
@Override
53+
protected void doWriteTo(StreamOutput out) throws IOException {
54+
out.writeNamedWriteable(format);
55+
out.writeDouble(value);
56+
out.writeDouble(sort);
57+
if (selectionCriteria != null) {
58+
selectionCriteria.writeTo(out);
59+
}
60+
}
61+
62+
@Override
63+
public double value() {
64+
return getValue();
65+
}
66+
67+
@Override
68+
public double getValue() {
69+
return value;
70+
}
71+
72+
double getSort() {
73+
return sort;
74+
}
75+
DocValueFormat getFormatter() {
76+
return format;
77+
}
78+
79+
@Override
80+
public String getWriteableName() {
81+
return MetricSelectorAggregationBuilder.NAME;
82+
}
83+
84+
@Override
85+
public InternalMetricSelector doReduce(List<InternalAggregation> aggregations, ReduceContext reduceContext) {
86+
Double bestValue = null;
87+
Double bestSort = null;
88+
89+
for (InternalAggregation aggregation : aggregations) {
90+
InternalMetricSelector metric = (InternalMetricSelector) aggregation;
91+
if (bestValue == null) {
92+
bestValue = metric.getValue();
93+
bestSort = metric.getSort();
94+
} else {
95+
if (metric.getSort() == selectionCriteria.select(bestSort, metric.getSort())) {
96+
bestSort = metric.getSort();
97+
bestValue = metric.getValue();
98+
}
99+
}
100+
}
101+
return new InternalMetricSelector(getName(), bestValue == null ? Double.NaN : bestValue,
102+
bestSort == null ? Double.NaN : bestSort, selectionCriteria, format, pipelineAggregators(), getMetaData());
103+
}
104+
@Override
105+
public XContentBuilder doXContentBody(XContentBuilder builder, Params params) throws IOException {
106+
builder.field(CommonFields.VALUE.getPreferredName(), Double.isNaN(value) ? null : getValue());
107+
builder.field(SORT_FIELD.getPreferredName(), Double.isNaN(sort) ? null : getSort());
108+
109+
String keyAsString = format.format(getSort()).toString();
110+
if (format != DocValueFormat.RAW) {
111+
builder.field(SORT_FIELD_AS_STRING.getPreferredName(), keyAsString);
112+
}
113+
return builder;
114+
}
115+
116+
@Override
117+
public int hashCode() {
118+
return Objects.hash(super.hashCode(), value, sort, format.getWriteableName());
119+
}
120+
121+
@Override
122+
public boolean equals(Object obj) {
123+
if (this == obj) return true;
124+
if (obj == null || getClass() != obj.getClass()) return false;
125+
if (super.equals(obj) == false) return false;
126+
InternalMetricSelector other = (InternalMetricSelector) obj;
127+
return Objects.equals(value, other.value) &&
128+
Objects.equals(sort, other.sort) &&
129+
Objects.equals(format.getWriteableName(), other.format.getWriteableName());
130+
}
131+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License;
4+
* you may not use this file except in compliance with the Elastic License.
5+
*/
6+
package org.elasticsearch.xpack.analytics.metricselector;
7+
8+
import org.elasticsearch.common.ParseField;
9+
import org.elasticsearch.common.io.stream.StreamInput;
10+
import org.elasticsearch.common.io.stream.StreamOutput;
11+
import org.elasticsearch.common.xcontent.ObjectParser;
12+
import org.elasticsearch.common.xcontent.ToXContent;
13+
import org.elasticsearch.common.xcontent.XContentBuilder;
14+
import org.elasticsearch.common.xcontent.XContentParser;
15+
import org.elasticsearch.index.query.QueryShardContext;
16+
import org.elasticsearch.search.DocValueFormat;
17+
import org.elasticsearch.search.MultiValueMode;
18+
import org.elasticsearch.search.aggregations.AggregationBuilder;
19+
import org.elasticsearch.search.aggregations.AggregatorFactories;
20+
import org.elasticsearch.search.aggregations.AggregatorFactory;
21+
import org.elasticsearch.search.aggregations.support.MultiValuesSourceAggregationBuilder;
22+
import org.elasticsearch.search.aggregations.support.MultiValuesSourceAggregatorFactory;
23+
import org.elasticsearch.search.aggregations.support.MultiValuesSourceFieldConfig;
24+
import org.elasticsearch.search.aggregations.support.MultiValuesSourceParseHelper;
25+
import org.elasticsearch.search.aggregations.support.ValueType;
26+
import org.elasticsearch.search.aggregations.support.ValuesSource;
27+
import org.elasticsearch.search.aggregations.support.ValuesSourceConfig;
28+
29+
import java.io.IOException;
30+
import java.util.Map;
31+
import java.util.Objects;
32+
33+
public class MetricSelectorAggregationBuilder extends MultiValuesSourceAggregationBuilder.LeafOnly<ValuesSource.Numeric, MetricSelectorAggregationBuilder> {
34+
public static final String NAME = "metric_selector";
35+
public static final ParseField METRIC_FIELD = new ParseField("metric_field");
36+
public static final ParseField SELECTOR_FIELD = new ParseField("selector_field");
37+
public static final ParseField MULTIVALUE_MODE_FIELD = new ParseField("multi_value_mode");
38+
39+
private SelectionCriteria selectionCriteria = SelectionCriteria.MAX;
40+
private MultiValueMode multiValueMode = MultiValueMode.AVG;
41+
42+
private static final ObjectParser<MetricSelectorAggregationBuilder, Void> PARSER;
43+
static {
44+
PARSER = new ObjectParser<>(MetricSelectorAggregationBuilder.NAME);
45+
MultiValuesSourceParseHelper.declareCommon(PARSER, true, ValueType.NUMERIC);
46+
MultiValuesSourceParseHelper.declareField(METRIC_FIELD.getPreferredName(), PARSER, true, false);
47+
MultiValuesSourceParseHelper.declareField(SELECTOR_FIELD.getPreferredName(), PARSER, true, false);
48+
PARSER.declareString(MetricSelectorAggregationBuilder::selectionCriteria, SelectionCriteria.SELECTION_CRITERIA);
49+
PARSER.declareString(MetricSelectorAggregationBuilder::multiValueMode, MULTIVALUE_MODE_FIELD);
50+
}
51+
52+
public static AggregationBuilder parse(String aggregationName, XContentParser parser) throws IOException {
53+
return PARSER.parse(parser, new MetricSelectorAggregationBuilder(aggregationName), null);
54+
}
55+
56+
public MetricSelectorAggregationBuilder(String name) {
57+
super(name, ValueType.NUMERIC);
58+
}
59+
60+
public MetricSelectorAggregationBuilder(MetricSelectorAggregationBuilder clone, AggregatorFactories.Builder factoriesBuilder, Map<String, Object> metaData) {
61+
super(clone, factoriesBuilder, metaData);
62+
}
63+
64+
public MetricSelectorAggregationBuilder metricField(MultiValuesSourceFieldConfig metricConfig) {
65+
metricConfig = Objects.requireNonNull(metricConfig, "Configuration for field [" + METRIC_FIELD + "] cannot be null");
66+
field(METRIC_FIELD.getPreferredName(), metricConfig);
67+
return this;
68+
}
69+
70+
public MetricSelectorAggregationBuilder selectorField(MultiValuesSourceFieldConfig selectorConfig) {
71+
selectorConfig = Objects.requireNonNull(selectorConfig, "Configuration for field [" + SELECTOR_FIELD + "] cannot be null");
72+
field(SELECTOR_FIELD.getPreferredName(), selectorConfig);
73+
return this;
74+
}
75+
76+
public MetricSelectorAggregationBuilder selectionCriteria(String criteria) {
77+
this.selectionCriteria = SelectionCriteria.fromString(criteria);
78+
return this;
79+
}
80+
81+
public MetricSelectorAggregationBuilder multiValueMode(String mode) {
82+
this.multiValueMode = MultiValueMode.fromString(mode);
83+
return this;
84+
}
85+
86+
/**
87+
* Read from a stream.
88+
*/
89+
public MetricSelectorAggregationBuilder(StreamInput in) throws IOException {
90+
super(in, ValueType.NUMERIC);
91+
}
92+
93+
@Override
94+
protected AggregationBuilder shallowCopy(AggregatorFactories.Builder factoriesBuilder, Map<String, Object> metaData) {
95+
return new MetricSelectorAggregationBuilder(this, factoriesBuilder, metaData);
96+
}
97+
98+
@Override
99+
protected void innerWriteTo(StreamOutput out) throws IOException {
100+
multiValueMode.writeTo(out);
101+
selectionCriteria.writeTo(out);
102+
}
103+
104+
@Override
105+
protected MultiValuesSourceAggregatorFactory<ValuesSource.Numeric> innerBuild(QueryShardContext queryShardContext,
106+
Map<String, ValuesSourceConfig<ValuesSource.Numeric>> configs,
107+
DocValueFormat format,
108+
AggregatorFactory parent,
109+
AggregatorFactories.Builder subFactoriesBuilder) throws IOException {
110+
return new MetricSelectorAggregatorFactory(name, configs, format, selectionCriteria, multiValueMode,
111+
queryShardContext, parent, subFactoriesBuilder, metaData);
112+
}
113+
114+
@Override
115+
public XContentBuilder doXContentBody(XContentBuilder builder, ToXContent.Params params) throws IOException {
116+
builder.field(MULTIVALUE_MODE_FIELD.getPreferredName(), multiValueMode);
117+
builder.field(SelectionCriteria.SELECTION_CRITERIA.getPreferredName(), selectionCriteria);
118+
return builder;
119+
}
120+
121+
@Override
122+
public String getType() {
123+
return NAME;
124+
}
125+
}

0 commit comments

Comments
 (0)