org.elasticsearch.search.aggregations.metrics.InternalExtendedStats Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of elasticsearch Show documentation
Show all versions of elasticsearch Show documentation
Elasticsearch subproject :distribution:archives:integ-test-zip
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
package org.elasticsearch.search.aggregations.metrics;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.search.DocValueFormat;
import org.elasticsearch.search.aggregations.InternalAggregation;
import org.elasticsearch.xcontent.XContentBuilder;
import java.io.IOException;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class InternalExtendedStats extends InternalStats implements ExtendedStats {
enum Metrics {
count,
sum,
min,
max,
avg,
sum_of_squares,
variance,
variance_population,
variance_sampling,
std_deviation,
std_deviation_population,
std_deviation_sampling,
std_upper,
std_lower,
std_upper_population,
std_lower_population,
std_upper_sampling,
std_lower_sampling;
public static Metrics resolve(String name) {
return Metrics.valueOf(name);
}
}
static final Set METRIC_NAMES = Collections.unmodifiableSet(
Stream.of(Metrics.values()).map(Metrics::name).collect(Collectors.toSet())
);
private final double sumOfSqrs;
private final double sigma;
public InternalExtendedStats(
String name,
long count,
double sum,
double min,
double max,
double sumOfSqrs,
double sigma,
DocValueFormat formatter,
Map metadata
) {
super(name, count, sum, min, max, formatter, metadata);
this.sumOfSqrs = sumOfSqrs;
this.sigma = sigma;
}
/**
* Read from a stream.
*/
public InternalExtendedStats(StreamInput in) throws IOException {
super(in);
sumOfSqrs = in.readDouble();
sigma = in.readDouble();
}
@Override
protected void writeOtherStatsTo(StreamOutput out) throws IOException {
out.writeDouble(sumOfSqrs);
out.writeDouble(sigma);
}
@Override
public String getWriteableName() {
return ExtendedStatsAggregationBuilder.NAME;
}
@Override
public double value(String name) {
if ("sum_of_squares".equals(name)) {
return sumOfSqrs;
}
if ("variance".equals(name)) {
return getVariance();
}
if ("variance_population".equals(name)) {
return getVariancePopulation();
}
if ("variance_sampling".equals(name)) {
return getVarianceSampling();
}
if ("std_deviation".equals(name)) {
return getStdDeviation();
}
if ("std_deviation_population".equals(name)) {
return getStdDeviationPopulation();
}
if ("std_deviation_sampling".equals(name)) {
return getStdDeviationSampling();
}
if ("std_upper".equals(name)) {
return getStdDeviationBound(Bounds.UPPER);
}
if ("std_lower".equals(name)) {
return getStdDeviationBound(Bounds.LOWER);
}
if ("std_upper_population".equals(name)) {
return getStdDeviationBound(Bounds.UPPER_POPULATION);
}
if ("std_lower_population".equals(name)) {
return getStdDeviationBound(Bounds.LOWER_POPULATION);
}
if ("std_upper_sampling".equals(name)) {
return getStdDeviationBound(Bounds.UPPER_SAMPLING);
}
if ("std_lower_sampling".equals(name)) {
return getStdDeviationBound(Bounds.LOWER_SAMPLING);
}
return super.value(name);
}
@Override
public Iterable valueNames() {
return METRIC_NAMES;
}
public double getSigma() {
return this.sigma;
}
@Override
public double getSumOfSquares() {
return sumOfSqrs;
}
@Override
public double getVariance() {
return getVariancePopulation();
}
@Override
public double getVariancePopulation() {
double variance = (sumOfSqrs - ((sum * sum) / count)) / count;
return variance < 0 ? 0 : variance;
}
@Override
public double getVarianceSampling() {
double variance = (sumOfSqrs - ((sum * sum) / count)) / (count - 1);
return variance < 0 ? 0 : variance;
}
@Override
public double getStdDeviation() {
return getStdDeviationPopulation();
}
@Override
public double getStdDeviationPopulation() {
return Math.sqrt(getVariancePopulation());
}
@Override
public double getStdDeviationSampling() {
return Math.sqrt(getVarianceSampling());
}
@Override
public double getStdDeviationBound(Bounds bound) {
switch (bound) {
case UPPER:
case UPPER_POPULATION:
return getAvg() + (getStdDeviationPopulation() * sigma);
case UPPER_SAMPLING:
return getAvg() + (getStdDeviationSampling() * sigma);
case LOWER:
case LOWER_POPULATION:
return getAvg() - (getStdDeviationPopulation() * sigma);
case LOWER_SAMPLING:
return getAvg() - (getStdDeviationSampling() * sigma);
default:
throw new IllegalArgumentException("Unknown bounds type " + bound);
}
}
@Override
public String getSumOfSquaresAsString() {
return valueAsString(Metrics.sum_of_squares.name());
}
@Override
public String getVarianceAsString() {
return valueAsString(Metrics.variance.name());
}
@Override
public String getVariancePopulationAsString() {
return valueAsString(Metrics.variance_population.name());
}
@Override
public String getVarianceSamplingAsString() {
return valueAsString(Metrics.variance_sampling.name());
}
@Override
public String getStdDeviationAsString() {
return valueAsString(Metrics.std_deviation.name());
}
@Override
public String getStdDeviationPopulationAsString() {
return valueAsString(Metrics.std_deviation_population.name());
}
@Override
public String getStdDeviationSamplingAsString() {
return valueAsString(Metrics.std_deviation_sampling.name());
}
@Override
public String getStdDeviationBoundAsString(Bounds bound) {
switch (bound) {
case UPPER:
return valueAsString(Metrics.std_upper.name());
case LOWER:
return valueAsString(Metrics.std_lower.name());
case UPPER_POPULATION:
return valueAsString(Metrics.std_upper_population.name());
case LOWER_POPULATION:
return valueAsString(Metrics.std_lower_population.name());
case UPPER_SAMPLING:
return valueAsString(Metrics.std_upper_sampling.name());
case LOWER_SAMPLING:
return valueAsString(Metrics.std_lower_sampling.name());
default:
throw new IllegalArgumentException("Unknown bounds type " + bound);
}
}
@Override
public InternalExtendedStats reduce(List aggregations, ReduceContext reduceContext) {
double sumOfSqrs = 0;
double compensationOfSqrs = 0;
for (InternalAggregation aggregation : aggregations) {
InternalExtendedStats stats = (InternalExtendedStats) aggregation;
if (stats.sigma != sigma) {
throw new IllegalStateException("Cannot reduce other stats aggregations that have a different sigma");
}
double value = stats.getSumOfSquares();
if (Double.isFinite(value) == false) {
sumOfSqrs += value;
} else if (Double.isFinite(sumOfSqrs)) {
double correctedOfSqrs = value - compensationOfSqrs;
double newSumOfSqrs = sumOfSqrs + correctedOfSqrs;
compensationOfSqrs = (newSumOfSqrs - sumOfSqrs) - correctedOfSqrs;
sumOfSqrs = newSumOfSqrs;
}
}
final InternalStats stats = super.reduce(aggregations, reduceContext);
return new InternalExtendedStats(
name,
stats.getCount(),
stats.getSum(),
stats.getMin(),
stats.getMax(),
sumOfSqrs,
sigma,
format,
getMetadata()
);
}
static class Fields {
public static final String SUM_OF_SQRS = "sum_of_squares";
public static final String SUM_OF_SQRS_AS_STRING = "sum_of_squares_as_string";
public static final String VARIANCE = "variance";
public static final String VARIANCE_AS_STRING = "variance_as_string";
public static final String VARIANCE_POPULATION = "variance_population";
public static final String VARIANCE_POPULATION_AS_STRING = "variance_population_as_string";
public static final String VARIANCE_SAMPLING = "variance_sampling";
public static final String VARIANCE_SAMPLING_AS_STRING = "variance_sampling_as_string";
public static final String STD_DEVIATION = "std_deviation";
public static final String STD_DEVIATION_AS_STRING = "std_deviation_as_string";
public static final String STD_DEVIATION_POPULATION = "std_deviation_population";
public static final String STD_DEVIATION_POPULATION_AS_STRING = "std_deviation_population_as_string";
public static final String STD_DEVIATION_SAMPLING = "std_deviation_sampling";
public static final String STD_DEVIATION_SAMPLING_AS_STRING = "std_deviation_sampling_as_string";
public static final String STD_DEVIATION_BOUNDS = "std_deviation_bounds";
public static final String STD_DEVIATION_BOUNDS_AS_STRING = "std_deviation_bounds_as_string";
public static final String UPPER = "upper";
public static final String LOWER = "lower";
public static final String UPPER_POPULATION = "upper_population";
public static final String LOWER_POPULATION = "lower_population";
public static final String UPPER_SAMPLING = "upper_sampling";
public static final String LOWER_SAMPLING = "lower_sampling";
}
@Override
protected XContentBuilder otherStatsToXContent(XContentBuilder builder, Params params) throws IOException {
if (count != 0) {
builder.field(Fields.SUM_OF_SQRS, sumOfSqrs);
builder.field(Fields.VARIANCE, getVariance());
builder.field(Fields.VARIANCE_POPULATION, getVariancePopulation());
builder.field(Fields.VARIANCE_SAMPLING, getVarianceSampling());
builder.field(Fields.STD_DEVIATION, getStdDeviation());
builder.field(Fields.STD_DEVIATION_POPULATION, getStdDeviationPopulation());
builder.field(Fields.STD_DEVIATION_SAMPLING, getStdDeviationSampling());
builder.startObject(Fields.STD_DEVIATION_BOUNDS);
{
builder.field(Fields.UPPER, getStdDeviationBound(Bounds.UPPER));
builder.field(Fields.LOWER, getStdDeviationBound(Bounds.LOWER));
builder.field(Fields.UPPER_POPULATION, getStdDeviationBound(Bounds.UPPER_POPULATION));
builder.field(Fields.LOWER_POPULATION, getStdDeviationBound(Bounds.LOWER_POPULATION));
builder.field(Fields.UPPER_SAMPLING, getStdDeviationBound(Bounds.UPPER_SAMPLING));
builder.field(Fields.LOWER_SAMPLING, getStdDeviationBound(Bounds.LOWER_SAMPLING));
}
builder.endObject();
if (format != DocValueFormat.RAW) {
builder.field(Fields.SUM_OF_SQRS_AS_STRING, format.format(sumOfSqrs));
builder.field(Fields.VARIANCE_AS_STRING, format.format(getVariance()));
builder.field(Fields.VARIANCE_POPULATION_AS_STRING, format.format(getVariancePopulation()));
builder.field(Fields.VARIANCE_SAMPLING_AS_STRING, format.format(getVarianceSampling()));
builder.field(Fields.STD_DEVIATION_AS_STRING, getStdDeviationAsString());
builder.field(Fields.STD_DEVIATION_POPULATION_AS_STRING, getStdDeviationPopulationAsString());
builder.field(Fields.STD_DEVIATION_SAMPLING_AS_STRING, getStdDeviationSamplingAsString());
builder.startObject(Fields.STD_DEVIATION_BOUNDS_AS_STRING);
{
builder.field(Fields.UPPER, getStdDeviationBoundAsString(Bounds.UPPER));
builder.field(Fields.LOWER, getStdDeviationBoundAsString(Bounds.LOWER));
builder.field(Fields.UPPER_POPULATION, getStdDeviationBoundAsString(Bounds.UPPER_POPULATION));
builder.field(Fields.LOWER_POPULATION, getStdDeviationBoundAsString(Bounds.LOWER_POPULATION));
builder.field(Fields.UPPER_SAMPLING, getStdDeviationBoundAsString(Bounds.UPPER_SAMPLING));
builder.field(Fields.LOWER_SAMPLING, getStdDeviationBoundAsString(Bounds.LOWER_SAMPLING));
}
builder.endObject();
}
} else {
builder.nullField(Fields.SUM_OF_SQRS);
builder.nullField(Fields.VARIANCE);
builder.nullField(Fields.VARIANCE_POPULATION);
builder.nullField(Fields.VARIANCE_SAMPLING);
builder.nullField(Fields.STD_DEVIATION);
builder.nullField(Fields.STD_DEVIATION_POPULATION);
builder.nullField(Fields.STD_DEVIATION_SAMPLING);
builder.startObject(Fields.STD_DEVIATION_BOUNDS);
{
builder.nullField(Fields.UPPER);
builder.nullField(Fields.LOWER);
builder.nullField(Fields.UPPER_POPULATION);
builder.nullField(Fields.LOWER_POPULATION);
builder.nullField(Fields.UPPER_SAMPLING);
builder.nullField(Fields.LOWER_SAMPLING);
}
builder.endObject();
}
return builder;
}
@Override
public int hashCode() {
return Objects.hash(super.hashCode(), sumOfSqrs, sigma);
}
@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;
InternalExtendedStats other = (InternalExtendedStats) obj;
return Double.compare(sumOfSqrs, other.sumOfSqrs) == 0 && Double.compare(sigma, other.sigma) == 0;
}
}