forked from elastic/elasticsearch
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
d7ae6de
commit 0299689
Showing
6 changed files
with
518 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
131 changes: 131 additions & 0 deletions
131
...rc/main/java/org/elasticsearch/xpack/analytics/metricselector/InternalMetricSelector.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,131 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License; | ||
* you may not use this file except in compliance with the Elastic License. | ||
*/ | ||
package org.elasticsearch.xpack.analytics.metricselector; | ||
|
||
import org.elasticsearch.common.ParseField; | ||
import org.elasticsearch.common.io.stream.StreamInput; | ||
import org.elasticsearch.common.io.stream.StreamOutput; | ||
import org.elasticsearch.common.xcontent.XContentBuilder; | ||
import org.elasticsearch.search.DocValueFormat; | ||
import org.elasticsearch.search.aggregations.InternalAggregation; | ||
import org.elasticsearch.search.aggregations.metrics.InternalNumericMetricsAggregation; | ||
import org.elasticsearch.search.aggregations.metrics.WeightedAvg; | ||
import org.elasticsearch.search.aggregations.pipeline.PipelineAggregator; | ||
|
||
import java.io.IOException; | ||
import java.util.List; | ||
import java.util.Map; | ||
import java.util.Objects; | ||
|
||
public class InternalMetricSelector extends InternalNumericMetricsAggregation.SingleValue implements WeightedAvg { | ||
private final double value; | ||
private final double sort; | ||
private final SelectionCriteria selectionCriteria; | ||
|
||
public static final ParseField SORT_FIELD = new ParseField("sort"); | ||
public static final ParseField SORT_FIELD_AS_STRING = new ParseField("sort_as_string"); | ||
|
||
InternalMetricSelector(String name, double value, double sort, SelectionCriteria selectionCriteria, | ||
DocValueFormat format, List<PipelineAggregator> pipelineAggregators, | ||
Map<String, Object> metaData) { | ||
super(name, pipelineAggregators, metaData); | ||
this.value = value; | ||
this.sort = sort; | ||
this.format = format; | ||
this.selectionCriteria = selectionCriteria; | ||
} | ||
|
||
/** | ||
* Read from a stream. | ||
*/ | ||
public InternalMetricSelector(StreamInput in) throws IOException { | ||
super(in); | ||
format = in.readNamedWriteable(DocValueFormat.class); | ||
value = in.readDouble(); | ||
sort = in.readDouble(); | ||
selectionCriteria = SelectionCriteria.fromStream(in); | ||
} | ||
|
||
@Override | ||
protected void doWriteTo(StreamOutput out) throws IOException { | ||
out.writeNamedWriteable(format); | ||
out.writeDouble(value); | ||
out.writeDouble(sort); | ||
if (selectionCriteria != null) { | ||
selectionCriteria.writeTo(out); | ||
} | ||
} | ||
|
||
@Override | ||
public double value() { | ||
return getValue(); | ||
} | ||
|
||
@Override | ||
public double getValue() { | ||
return value; | ||
} | ||
|
||
double getSort() { | ||
return sort; | ||
} | ||
DocValueFormat getFormatter() { | ||
return format; | ||
} | ||
|
||
@Override | ||
public String getWriteableName() { | ||
return MetricSelectorAggregationBuilder.NAME; | ||
} | ||
|
||
@Override | ||
public InternalMetricSelector doReduce(List<InternalAggregation> aggregations, ReduceContext reduceContext) { | ||
Double bestValue = null; | ||
Double bestSort = null; | ||
|
||
for (InternalAggregation aggregation : aggregations) { | ||
InternalMetricSelector metric = (InternalMetricSelector) aggregation; | ||
if (bestValue == null) { | ||
bestValue = metric.getValue(); | ||
bestSort = metric.getSort(); | ||
} else { | ||
if (metric.getSort() == selectionCriteria.select(bestSort, metric.getSort())) { | ||
bestSort = metric.getSort(); | ||
bestValue = metric.getValue(); | ||
} | ||
} | ||
} | ||
return new InternalMetricSelector(getName(), bestValue == null ? Double.NaN : bestValue, | ||
bestSort == null ? Double.NaN : bestSort, selectionCriteria, format, pipelineAggregators(), getMetaData()); | ||
} | ||
@Override | ||
public XContentBuilder doXContentBody(XContentBuilder builder, Params params) throws IOException { | ||
builder.field(CommonFields.VALUE.getPreferredName(), Double.isNaN(value) ? null : getValue()); | ||
builder.field(SORT_FIELD.getPreferredName(), Double.isNaN(sort) ? null : getSort()); | ||
|
||
String keyAsString = format.format(getSort()).toString(); | ||
if (format != DocValueFormat.RAW) { | ||
builder.field(SORT_FIELD_AS_STRING.getPreferredName(), keyAsString); | ||
} | ||
return builder; | ||
} | ||
|
||
@Override | ||
public int hashCode() { | ||
return Objects.hash(super.hashCode(), value, sort, format.getWriteableName()); | ||
} | ||
|
||
@Override | ||
public boolean equals(Object obj) { | ||
if (this == obj) return true; | ||
if (obj == null || getClass() != obj.getClass()) return false; | ||
if (super.equals(obj) == false) return false; | ||
InternalMetricSelector other = (InternalMetricSelector) obj; | ||
return Objects.equals(value, other.value) && | ||
Objects.equals(sort, other.sort) && | ||
Objects.equals(format.getWriteableName(), other.format.getWriteableName()); | ||
} | ||
} |
125 changes: 125 additions & 0 deletions
125
...va/org/elasticsearch/xpack/analytics/metricselector/MetricSelectorAggregationBuilder.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License; | ||
* you may not use this file except in compliance with the Elastic License. | ||
*/ | ||
package org.elasticsearch.xpack.analytics.metricselector; | ||
|
||
import org.elasticsearch.common.ParseField; | ||
import org.elasticsearch.common.io.stream.StreamInput; | ||
import org.elasticsearch.common.io.stream.StreamOutput; | ||
import org.elasticsearch.common.xcontent.ObjectParser; | ||
import org.elasticsearch.common.xcontent.ToXContent; | ||
import org.elasticsearch.common.xcontent.XContentBuilder; | ||
import org.elasticsearch.common.xcontent.XContentParser; | ||
import org.elasticsearch.index.query.QueryShardContext; | ||
import org.elasticsearch.search.DocValueFormat; | ||
import org.elasticsearch.search.MultiValueMode; | ||
import org.elasticsearch.search.aggregations.AggregationBuilder; | ||
import org.elasticsearch.search.aggregations.AggregatorFactories; | ||
import org.elasticsearch.search.aggregations.AggregatorFactory; | ||
import org.elasticsearch.search.aggregations.support.MultiValuesSourceAggregationBuilder; | ||
import org.elasticsearch.search.aggregations.support.MultiValuesSourceAggregatorFactory; | ||
import org.elasticsearch.search.aggregations.support.MultiValuesSourceFieldConfig; | ||
import org.elasticsearch.search.aggregations.support.MultiValuesSourceParseHelper; | ||
import org.elasticsearch.search.aggregations.support.ValueType; | ||
import org.elasticsearch.search.aggregations.support.ValuesSource; | ||
import org.elasticsearch.search.aggregations.support.ValuesSourceConfig; | ||
|
||
import java.io.IOException; | ||
import java.util.Map; | ||
import java.util.Objects; | ||
|
||
public class MetricSelectorAggregationBuilder extends MultiValuesSourceAggregationBuilder.LeafOnly<ValuesSource.Numeric, MetricSelectorAggregationBuilder> { | ||
public static final String NAME = "metric_selector"; | ||
public static final ParseField METRIC_FIELD = new ParseField("metric_field"); | ||
public static final ParseField SELECTOR_FIELD = new ParseField("selector_field"); | ||
public static final ParseField MULTIVALUE_MODE_FIELD = new ParseField("multi_value_mode"); | ||
|
||
private SelectionCriteria selectionCriteria = SelectionCriteria.MAX; | ||
private MultiValueMode multiValueMode = MultiValueMode.AVG; | ||
|
||
private static final ObjectParser<MetricSelectorAggregationBuilder, Void> PARSER; | ||
static { | ||
PARSER = new ObjectParser<>(MetricSelectorAggregationBuilder.NAME); | ||
MultiValuesSourceParseHelper.declareCommon(PARSER, true, ValueType.NUMERIC); | ||
MultiValuesSourceParseHelper.declareField(METRIC_FIELD.getPreferredName(), PARSER, true, false); | ||
MultiValuesSourceParseHelper.declareField(SELECTOR_FIELD.getPreferredName(), PARSER, true, false); | ||
PARSER.declareString(MetricSelectorAggregationBuilder::selectionCriteria, SelectionCriteria.SELECTION_CRITERIA); | ||
PARSER.declareString(MetricSelectorAggregationBuilder::multiValueMode, MULTIVALUE_MODE_FIELD); | ||
} | ||
|
||
public static AggregationBuilder parse(String aggregationName, XContentParser parser) throws IOException { | ||
return PARSER.parse(parser, new MetricSelectorAggregationBuilder(aggregationName), null); | ||
} | ||
|
||
public MetricSelectorAggregationBuilder(String name) { | ||
super(name, ValueType.NUMERIC); | ||
} | ||
|
||
public MetricSelectorAggregationBuilder(MetricSelectorAggregationBuilder clone, AggregatorFactories.Builder factoriesBuilder, Map<String, Object> metaData) { | ||
super(clone, factoriesBuilder, metaData); | ||
} | ||
|
||
public MetricSelectorAggregationBuilder metricField(MultiValuesSourceFieldConfig metricConfig) { | ||
metricConfig = Objects.requireNonNull(metricConfig, "Configuration for field [" + METRIC_FIELD + "] cannot be null"); | ||
field(METRIC_FIELD.getPreferredName(), metricConfig); | ||
return this; | ||
} | ||
|
||
public MetricSelectorAggregationBuilder selectorField(MultiValuesSourceFieldConfig selectorConfig) { | ||
selectorConfig = Objects.requireNonNull(selectorConfig, "Configuration for field [" + SELECTOR_FIELD + "] cannot be null"); | ||
field(SELECTOR_FIELD.getPreferredName(), selectorConfig); | ||
return this; | ||
} | ||
|
||
public MetricSelectorAggregationBuilder selectionCriteria(String criteria) { | ||
this.selectionCriteria = SelectionCriteria.fromString(criteria); | ||
return this; | ||
} | ||
|
||
public MetricSelectorAggregationBuilder multiValueMode(String mode) { | ||
this.multiValueMode = MultiValueMode.fromString(mode); | ||
return this; | ||
} | ||
|
||
/** | ||
* Read from a stream. | ||
*/ | ||
public MetricSelectorAggregationBuilder(StreamInput in) throws IOException { | ||
super(in, ValueType.NUMERIC); | ||
} | ||
|
||
@Override | ||
protected AggregationBuilder shallowCopy(AggregatorFactories.Builder factoriesBuilder, Map<String, Object> metaData) { | ||
return new MetricSelectorAggregationBuilder(this, factoriesBuilder, metaData); | ||
} | ||
|
||
@Override | ||
protected void innerWriteTo(StreamOutput out) throws IOException { | ||
multiValueMode.writeTo(out); | ||
selectionCriteria.writeTo(out); | ||
} | ||
|
||
@Override | ||
protected MultiValuesSourceAggregatorFactory<ValuesSource.Numeric> innerBuild(QueryShardContext queryShardContext, | ||
Map<String, ValuesSourceConfig<ValuesSource.Numeric>> configs, | ||
DocValueFormat format, | ||
AggregatorFactory parent, | ||
AggregatorFactories.Builder subFactoriesBuilder) throws IOException { | ||
return new MetricSelectorAggregatorFactory(name, configs, format, selectionCriteria, multiValueMode, | ||
queryShardContext, parent, subFactoriesBuilder, metaData); | ||
} | ||
|
||
@Override | ||
public XContentBuilder doXContentBody(XContentBuilder builder, ToXContent.Params params) throws IOException { | ||
builder.field(MULTIVALUE_MODE_FIELD.getPreferredName(), multiValueMode); | ||
builder.field(SelectionCriteria.SELECTION_CRITERIA.getPreferredName(), selectionCriteria); | ||
return builder; | ||
} | ||
|
||
@Override | ||
public String getType() { | ||
return NAME; | ||
} | ||
} |
Oops, something went wrong.