diff --git a/src/main/java/org/elasticsearch/search/aggregations/metrics/InternalNumericMetricsAggregation.java b/src/main/java/org/elasticsearch/search/aggregations/metrics/InternalNumericMetricsAggregation.java index a8587e2bb55..0c301e30bde 100644 --- a/src/main/java/org/elasticsearch/search/aggregations/metrics/InternalNumericMetricsAggregation.java +++ b/src/main/java/org/elasticsearch/search/aggregations/metrics/InternalNumericMetricsAggregation.java @@ -31,7 +31,7 @@ public abstract class InternalNumericMetricsAggregation extends InternalMetricsA protected ValueFormatter valueFormatter; - public static abstract class SingleValue extends InternalNumericMetricsAggregation { + public static abstract class SingleValue extends InternalNumericMetricsAggregation implements NumericMetricsAggregation.SingleValue { protected SingleValue() {} @@ -39,7 +39,13 @@ public abstract class InternalNumericMetricsAggregation extends InternalMetricsA super(name, metaData); } - public abstract double value(); + public String getValueAsString() { + if (valueFormatter == null) { + return ValueFormatter.RAW.format(value()); + } else { + return valueFormatter.format(value()); + } + } @Override public Object getProperty(List path) { @@ -54,7 +60,7 @@ public abstract class InternalNumericMetricsAggregation extends InternalMetricsA } - public static abstract class MultiValue extends InternalNumericMetricsAggregation { + public static abstract class MultiValue extends InternalNumericMetricsAggregation implements NumericMetricsAggregation.MultiValue { protected MultiValue() {} @@ -64,6 +70,14 @@ public abstract class InternalNumericMetricsAggregation extends InternalMetricsA public abstract double value(String name); + public String valueAsString(String name) { + if (valueFormatter == null) { + return ValueFormatter.RAW.format(value(name)); + } else { + return valueFormatter.format(value(name)); + } + } + @Override public Object getProperty(List path) { if (path.isEmpty()) { diff --git a/src/main/java/org/elasticsearch/search/aggregations/metrics/NumericMetricsAggregation.java b/src/main/java/org/elasticsearch/search/aggregations/metrics/NumericMetricsAggregation.java new file mode 100644 index 00000000000..11083c9a061 --- /dev/null +++ b/src/main/java/org/elasticsearch/search/aggregations/metrics/NumericMetricsAggregation.java @@ -0,0 +1,36 @@ +/* + * Licensed to Elasticsearch under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.elasticsearch.search.aggregations.metrics; + +import org.elasticsearch.search.aggregations.Aggregation; + +public interface NumericMetricsAggregation extends Aggregation { + + public static interface SingleValue extends NumericMetricsAggregation { + + double value(); + + String getValueAsString(); + + } + + public static interface MultiValue extends NumericMetricsAggregation { + } +} diff --git a/src/main/java/org/elasticsearch/search/aggregations/metrics/NumericValuesSourceMetricsAggregatorParser.java b/src/main/java/org/elasticsearch/search/aggregations/metrics/NumericValuesSourceMetricsAggregatorParser.java index f5d9ded3d71..ae9e6844e2f 100644 --- a/src/main/java/org/elasticsearch/search/aggregations/metrics/NumericValuesSourceMetricsAggregatorParser.java +++ b/src/main/java/org/elasticsearch/search/aggregations/metrics/NumericValuesSourceMetricsAggregatorParser.java @@ -49,7 +49,7 @@ public abstract class NumericValuesSourceMetricsAggregatorParser vsParser = ValuesSourceParser.numeric(aggregationName, aggType, context) + ValuesSourceParser vsParser = ValuesSourceParser.numeric(aggregationName, aggType, context).formattable(true) .build(); XContentParser.Token token; diff --git a/src/main/java/org/elasticsearch/search/aggregations/metrics/ValuesSourceMetricsAggregationBuilder.java b/src/main/java/org/elasticsearch/search/aggregations/metrics/ValuesSourceMetricsAggregationBuilder.java index bbf1827e00e..dd97b3ccfb6 100644 --- a/src/main/java/org/elasticsearch/search/aggregations/metrics/ValuesSourceMetricsAggregationBuilder.java +++ b/src/main/java/org/elasticsearch/search/aggregations/metrics/ValuesSourceMetricsAggregationBuilder.java @@ -20,6 +20,7 @@ package org.elasticsearch.search.aggregations.metrics; import com.google.common.collect.Maps; + import org.elasticsearch.common.xcontent.XContentBuilder; import java.io.IOException; @@ -33,6 +34,7 @@ public abstract class ValuesSourceMetricsAggregationBuilder params; protected ValuesSourceMetricsAggregationBuilder(String name, String type) { @@ -57,6 +59,12 @@ public abstract class ValuesSourceMetricsAggregationBuilder params) { if (this.params == null) { @@ -90,6 +98,10 @@ public abstract class ValuesSourceMetricsAggregationBuilder metaData) { + public AvgAggregator(String name, long estimatedBucketsCount, ValuesSource.Numeric valuesSource, @Nullable ValueFormatter formatter, + AggregationContext context, Aggregator parent, Map metaData) { super(name, estimatedBucketsCount, context, parent, metaData); this.valuesSource = valuesSource; + this.formatter = formatter; if (valuesSource != null) { final long initialSize = estimatedBucketsCount < 2 ? 1 : estimatedBucketsCount; counts = bigArrays.newLongArray(initialSize, true); @@ -88,14 +93,14 @@ public class AvgAggregator extends NumericMetricsAggregator.SingleValue { @Override public InternalAggregation buildAggregation(long owningBucketOrdinal) { if (valuesSource == null || owningBucketOrdinal >= counts.size()) { - return new InternalAvg(name, 0l, 0, getMetaData()); + return new InternalAvg(name, 0l, 0, formatter, getMetaData()); } - return new InternalAvg(name, sums.get(owningBucketOrdinal), counts.get(owningBucketOrdinal), getMetaData()); + return new InternalAvg(name, sums.get(owningBucketOrdinal), counts.get(owningBucketOrdinal), formatter, getMetaData()); } @Override public InternalAggregation buildEmptyAggregation() { - return new InternalAvg(name, 0.0, 0l, getMetaData()); + return new InternalAvg(name, 0.0, 0l, formatter, getMetaData()); } public static class Factory extends ValuesSourceAggregatorFactory.LeafOnly> { @@ -106,12 +111,12 @@ public class AvgAggregator extends NumericMetricsAggregator.SingleValue { @Override protected Aggregator createUnmapped(AggregationContext aggregationContext, Aggregator parent, Map metaData) { - return new AvgAggregator(name, 0, null, aggregationContext, parent, metaData); + return new AvgAggregator(name, 0, null, config.formatter(), aggregationContext, parent, metaData); } @Override protected Aggregator create(ValuesSource.Numeric valuesSource, long expectedBucketsCount, AggregationContext aggregationContext, Aggregator parent, Map metaData) { - return new AvgAggregator(name, expectedBucketsCount, valuesSource, aggregationContext, parent, metaData); + return new AvgAggregator(name, expectedBucketsCount, valuesSource, config.formatter(), aggregationContext, parent, metaData); } } diff --git a/src/main/java/org/elasticsearch/search/aggregations/metrics/avg/InternalAvg.java b/src/main/java/org/elasticsearch/search/aggregations/metrics/avg/InternalAvg.java index ca8a66d1b17..dcdecbe3b67 100644 --- a/src/main/java/org/elasticsearch/search/aggregations/metrics/avg/InternalAvg.java +++ b/src/main/java/org/elasticsearch/search/aggregations/metrics/avg/InternalAvg.java @@ -18,12 +18,14 @@ */ package org.elasticsearch.search.aggregations.metrics.avg; +import org.elasticsearch.common.inject.internal.Nullable; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.search.aggregations.AggregationStreams; import org.elasticsearch.search.aggregations.InternalAggregation; import org.elasticsearch.search.aggregations.metrics.InternalNumericMetricsAggregation; +import org.elasticsearch.search.aggregations.support.format.ValueFormatter; import org.elasticsearch.search.aggregations.support.format.ValueFormatterStreams; import java.io.IOException; @@ -54,10 +56,11 @@ public class InternalAvg extends InternalNumericMetricsAggregation.SingleValue i InternalAvg() {} // for serialization - public InternalAvg(String name, double sum, long count, Map metaData) { + public InternalAvg(String name, double sum, long count, @Nullable ValueFormatter formatter, Map metaData) { super(name, metaData); this.sum = sum; this.count = count; + this.valueFormatter = formatter; } @Override @@ -82,7 +85,7 @@ public class InternalAvg extends InternalNumericMetricsAggregation.SingleValue i count += ((InternalAvg) aggregation).count; sum += ((InternalAvg) aggregation).sum; } - return new InternalAvg(getName(), sum, count, getMetaData()); + return new InternalAvg(getName(), sum, count, valueFormatter, getMetaData()); } @Override diff --git a/src/main/java/org/elasticsearch/search/aggregations/metrics/cardinality/Cardinality.java b/src/main/java/org/elasticsearch/search/aggregations/metrics/cardinality/Cardinality.java index 7efe88ad295..f9d8e10730a 100644 --- a/src/main/java/org/elasticsearch/search/aggregations/metrics/cardinality/Cardinality.java +++ b/src/main/java/org/elasticsearch/search/aggregations/metrics/cardinality/Cardinality.java @@ -19,12 +19,12 @@ package org.elasticsearch.search.aggregations.metrics.cardinality; -import org.elasticsearch.search.aggregations.Aggregation; +import org.elasticsearch.search.aggregations.metrics.NumericMetricsAggregation; /** * An aggregation that computes approximate numbers of unique terms. */ -public interface Cardinality extends Aggregation { +public interface Cardinality extends NumericMetricsAggregation.SingleValue { /** * The number of unique terms. diff --git a/src/main/java/org/elasticsearch/search/aggregations/metrics/cardinality/CardinalityAggregator.java b/src/main/java/org/elasticsearch/search/aggregations/metrics/cardinality/CardinalityAggregator.java index 169687690bd..205a9e43b69 100644 --- a/src/main/java/org/elasticsearch/search/aggregations/metrics/cardinality/CardinalityAggregator.java +++ b/src/main/java/org/elasticsearch/search/aggregations/metrics/cardinality/CardinalityAggregator.java @@ -21,6 +21,7 @@ package org.elasticsearch.search.aggregations.metrics.cardinality; import com.carrotsearch.hppc.hash.MurmurHash3; import com.google.common.base.Preconditions; + import org.apache.lucene.index.LeafReaderContext; import org.apache.lucene.index.RandomAccessOrds; import org.apache.lucene.index.SortedNumericDocValues; @@ -42,6 +43,7 @@ import org.elasticsearch.search.aggregations.InternalAggregation; import org.elasticsearch.search.aggregations.metrics.NumericMetricsAggregator; import org.elasticsearch.search.aggregations.support.AggregationContext; import org.elasticsearch.search.aggregations.support.ValuesSource; +import org.elasticsearch.search.aggregations.support.format.ValueFormatter; import java.io.IOException; import java.util.Map; @@ -60,14 +62,17 @@ public class CardinalityAggregator extends NumericMetricsAggregator.SingleValue private HyperLogLogPlusPlus counts; private Collector collector; + private ValueFormatter formatter; public CardinalityAggregator(String name, long estimatedBucketsCount, ValuesSource valuesSource, boolean rehash, - int precision, AggregationContext context, Aggregator parent, Map metaData) { + int precision, + @Nullable ValueFormatter formatter, AggregationContext context, Aggregator parent, Map metaData) { super(name, estimatedBucketsCount, context, parent, metaData); this.valuesSource = valuesSource; this.rehash = rehash; this.precision = precision; this.counts = valuesSource == null ? null : new HyperLogLogPlusPlus(precision, bigArrays, estimatedBucketsCount); + this.formatter = formatter; } @Override @@ -152,12 +157,12 @@ public class CardinalityAggregator extends NumericMetricsAggregator.SingleValue // this Aggregator (and its HLL++ counters) is released. HyperLogLogPlusPlus copy = new HyperLogLogPlusPlus(precision, BigArrays.NON_RECYCLING_INSTANCE, 1); copy.merge(0, counts, owningBucketOrdinal); - return new InternalCardinality(name, copy, getMetaData()); + return new InternalCardinality(name, copy, formatter, getMetaData()); } @Override public InternalAggregation buildEmptyAggregation() { - return new InternalCardinality(name, null, getMetaData()); + return new InternalCardinality(name, null, formatter, getMetaData()); } @Override diff --git a/src/main/java/org/elasticsearch/search/aggregations/metrics/cardinality/CardinalityAggregatorFactory.java b/src/main/java/org/elasticsearch/search/aggregations/metrics/cardinality/CardinalityAggregatorFactory.java index 7a4419e2f91..c52c4ad4fb1 100644 --- a/src/main/java/org/elasticsearch/search/aggregations/metrics/cardinality/CardinalityAggregatorFactory.java +++ b/src/main/java/org/elasticsearch/search/aggregations/metrics/cardinality/CardinalityAggregatorFactory.java @@ -46,7 +46,8 @@ final class CardinalityAggregatorFactory extends ValuesSourceAggregatorFactory metaData) { - return new CardinalityAggregator(name, parent == null ? 1 : parent.estimatedBucketCount(), null, true, precision(parent), context, parent, metaData); + return new CardinalityAggregator(name, parent == null ? 1 : parent.estimatedBucketCount(), null, true, precision(parent), + config.formatter(), context, parent, metaData); } @Override @@ -54,7 +55,8 @@ final class CardinalityAggregatorFactory extends ValuesSourceAggregatorFactory metaData) { + InternalCardinality(String name, HyperLogLogPlusPlus counts, @Nullable ValueFormatter formatter, Map metaData) { super(name, metaData); this.counts = counts; + this.valueFormatter = formatter; } private InternalCardinality() { @@ -103,7 +106,8 @@ public final class InternalCardinality extends InternalNumericMetricsAggregation final InternalCardinality cardinality = (InternalCardinality) aggregation; if (cardinality.counts != null) { if (reduced == null) { - reduced = new InternalCardinality(name, new HyperLogLogPlusPlus(cardinality.counts.precision(), BigArrays.NON_RECYCLING_INSTANCE, 1), getMetaData()); + reduced = new InternalCardinality(name, new HyperLogLogPlusPlus(cardinality.counts.precision(), + BigArrays.NON_RECYCLING_INSTANCE, 1), this.valueFormatter, getMetaData()); } reduced.merge(cardinality); } diff --git a/src/main/java/org/elasticsearch/search/aggregations/metrics/max/InternalMax.java b/src/main/java/org/elasticsearch/search/aggregations/metrics/max/InternalMax.java index f0675e62fdd..90486f3b620 100644 --- a/src/main/java/org/elasticsearch/search/aggregations/metrics/max/InternalMax.java +++ b/src/main/java/org/elasticsearch/search/aggregations/metrics/max/InternalMax.java @@ -18,12 +18,14 @@ */ package org.elasticsearch.search.aggregations.metrics.max; +import org.elasticsearch.common.inject.internal.Nullable; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.search.aggregations.AggregationStreams; import org.elasticsearch.search.aggregations.InternalAggregation; import org.elasticsearch.search.aggregations.metrics.InternalNumericMetricsAggregation; +import org.elasticsearch.search.aggregations.support.format.ValueFormatter; import org.elasticsearch.search.aggregations.support.format.ValueFormatterStreams; import java.io.IOException; @@ -53,8 +55,9 @@ public class InternalMax extends InternalNumericMetricsAggregation.SingleValue i InternalMax() {} // for serialization - public InternalMax(String name, double max, Map metaData) { + public InternalMax(String name, double max, @Nullable ValueFormatter formatter, Map metaData) { super(name, metaData); + this.valueFormatter = formatter; this.max = max; } @@ -78,7 +81,7 @@ public class InternalMax extends InternalNumericMetricsAggregation.SingleValue i for (InternalAggregation aggregation : reduceContext.aggregations()) { max = Math.max(max, ((InternalMax) aggregation).max); } - return new InternalMax(name, max, getMetaData()); + return new InternalMax(name, max, valueFormatter, getMetaData()); } @Override diff --git a/src/main/java/org/elasticsearch/search/aggregations/metrics/max/Max.java b/src/main/java/org/elasticsearch/search/aggregations/metrics/max/Max.java index 99c5905ead7..bee808d16a1 100644 --- a/src/main/java/org/elasticsearch/search/aggregations/metrics/max/Max.java +++ b/src/main/java/org/elasticsearch/search/aggregations/metrics/max/Max.java @@ -18,12 +18,12 @@ */ package org.elasticsearch.search.aggregations.metrics.max; -import org.elasticsearch.search.aggregations.Aggregation; +import org.elasticsearch.search.aggregations.metrics.NumericMetricsAggregation; /** * An aggregation that computes the maximum of the values in the current bucket. */ -public interface Max extends Aggregation { +public interface Max extends NumericMetricsAggregation.SingleValue { /** * The maximum. diff --git a/src/main/java/org/elasticsearch/search/aggregations/metrics/max/MaxAggregator.java b/src/main/java/org/elasticsearch/search/aggregations/metrics/max/MaxAggregator.java index d073c47f050..9214f47ab60 100644 --- a/src/main/java/org/elasticsearch/search/aggregations/metrics/max/MaxAggregator.java +++ b/src/main/java/org/elasticsearch/search/aggregations/metrics/max/MaxAggregator.java @@ -19,6 +19,7 @@ package org.elasticsearch.search.aggregations.metrics.max; import org.apache.lucene.index.LeafReaderContext; +import org.elasticsearch.common.inject.internal.Nullable; import org.elasticsearch.common.lease.Releasables; import org.elasticsearch.common.util.DoubleArray; import org.elasticsearch.index.fielddata.NumericDoubleValues; @@ -31,6 +32,7 @@ import org.elasticsearch.search.aggregations.support.AggregationContext; import org.elasticsearch.search.aggregations.support.ValuesSource; import org.elasticsearch.search.aggregations.support.ValuesSourceAggregatorFactory; import org.elasticsearch.search.aggregations.support.ValuesSourceConfig; +import org.elasticsearch.search.aggregations.support.format.ValueFormatter; import java.io.IOException; import java.util.Map; @@ -44,10 +46,13 @@ public class MaxAggregator extends NumericMetricsAggregator.SingleValue { private NumericDoubleValues values; private DoubleArray maxes; + private ValueFormatter formatter; - public MaxAggregator(String name, long estimatedBucketsCount, ValuesSource.Numeric valuesSource, AggregationContext context, Aggregator parent, Map metaData) { + public MaxAggregator(String name, long estimatedBucketsCount, ValuesSource.Numeric valuesSource, @Nullable ValueFormatter formatter, + AggregationContext context, Aggregator parent, Map metaData) { super(name, estimatedBucketsCount, context, parent, metaData); this.valuesSource = valuesSource; + this.formatter = formatter; if (valuesSource != null) { final long initialSize = estimatedBucketsCount < 2 ? 1 : estimatedBucketsCount; maxes = bigArrays.newDoubleArray(initialSize, false); @@ -87,15 +92,15 @@ public class MaxAggregator extends NumericMetricsAggregator.SingleValue { @Override public InternalAggregation buildAggregation(long owningBucketOrdinal) { if (valuesSource == null) { - return new InternalMax(name, Double.NEGATIVE_INFINITY, getMetaData()); + return new InternalMax(name, Double.NEGATIVE_INFINITY, formatter, getMetaData()); } assert owningBucketOrdinal < maxes.size(); - return new InternalMax(name, maxes.get(owningBucketOrdinal), getMetaData()); + return new InternalMax(name, maxes.get(owningBucketOrdinal), formatter, getMetaData()); } @Override public InternalAggregation buildEmptyAggregation() { - return new InternalMax(name, Double.NEGATIVE_INFINITY, getMetaData()); + return new InternalMax(name, Double.NEGATIVE_INFINITY, formatter, getMetaData()); } public static class Factory extends ValuesSourceAggregatorFactory.LeafOnly> { @@ -106,12 +111,12 @@ public class MaxAggregator extends NumericMetricsAggregator.SingleValue { @Override protected Aggregator createUnmapped(AggregationContext aggregationContext, Aggregator parent, Map metaData) { - return new MaxAggregator(name, 0, null, aggregationContext, parent, metaData); + return new MaxAggregator(name, 0, null, config.formatter(), aggregationContext, parent, metaData); } @Override protected Aggregator create(ValuesSource.Numeric valuesSource, long expectedBucketsCount, AggregationContext aggregationContext, Aggregator parent, Map metaData) { - return new MaxAggregator(name, expectedBucketsCount, valuesSource, aggregationContext, parent, metaData); + return new MaxAggregator(name, expectedBucketsCount, valuesSource, config.formatter(), aggregationContext, parent, metaData); } } diff --git a/src/main/java/org/elasticsearch/search/aggregations/metrics/min/InternalMin.java b/src/main/java/org/elasticsearch/search/aggregations/metrics/min/InternalMin.java index 4dfa6e5624d..554152e486c 100644 --- a/src/main/java/org/elasticsearch/search/aggregations/metrics/min/InternalMin.java +++ b/src/main/java/org/elasticsearch/search/aggregations/metrics/min/InternalMin.java @@ -18,12 +18,14 @@ */ package org.elasticsearch.search.aggregations.metrics.min; +import org.elasticsearch.common.inject.internal.Nullable; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.search.aggregations.AggregationStreams; import org.elasticsearch.search.aggregations.InternalAggregation; import org.elasticsearch.search.aggregations.metrics.InternalNumericMetricsAggregation; +import org.elasticsearch.search.aggregations.support.format.ValueFormatter; import org.elasticsearch.search.aggregations.support.format.ValueFormatterStreams; import java.io.IOException; @@ -54,9 +56,10 @@ public class InternalMin extends InternalNumericMetricsAggregation.SingleValue i InternalMin() {} // for serialization - public InternalMin(String name, double min, Map metaData) { + public InternalMin(String name, double min, @Nullable ValueFormatter formatter, Map metaData) { super(name, metaData); this.min = min; + this.valueFormatter = formatter; } @Override @@ -79,7 +82,7 @@ public class InternalMin extends InternalNumericMetricsAggregation.SingleValue i for (InternalAggregation aggregation : reduceContext.aggregations()) { min = Math.min(min, ((InternalMin) aggregation).min); } - return new InternalMin(getName(), min, getMetaData()); + return new InternalMin(getName(), min, this.valueFormatter, getMetaData()); } @Override diff --git a/src/main/java/org/elasticsearch/search/aggregations/metrics/min/Min.java b/src/main/java/org/elasticsearch/search/aggregations/metrics/min/Min.java index a8144ec826f..3b5488199e8 100644 --- a/src/main/java/org/elasticsearch/search/aggregations/metrics/min/Min.java +++ b/src/main/java/org/elasticsearch/search/aggregations/metrics/min/Min.java @@ -18,12 +18,12 @@ */ package org.elasticsearch.search.aggregations.metrics.min; -import org.elasticsearch.search.aggregations.Aggregation; +import org.elasticsearch.search.aggregations.metrics.NumericMetricsAggregation; /** * An aggregation that computes the minimum of the values in the current bucket. */ -public interface Min extends Aggregation { +public interface Min extends NumericMetricsAggregation.SingleValue { /** * The minimum. diff --git a/src/main/java/org/elasticsearch/search/aggregations/metrics/min/MinAggregator.java b/src/main/java/org/elasticsearch/search/aggregations/metrics/min/MinAggregator.java index 59128e24215..26d2268f22c 100644 --- a/src/main/java/org/elasticsearch/search/aggregations/metrics/min/MinAggregator.java +++ b/src/main/java/org/elasticsearch/search/aggregations/metrics/min/MinAggregator.java @@ -19,6 +19,7 @@ package org.elasticsearch.search.aggregations.metrics.min; import org.apache.lucene.index.LeafReaderContext; +import org.elasticsearch.common.inject.internal.Nullable; import org.elasticsearch.common.lease.Releasables; import org.elasticsearch.common.util.DoubleArray; import org.elasticsearch.index.fielddata.NumericDoubleValues; @@ -31,6 +32,7 @@ import org.elasticsearch.search.aggregations.support.AggregationContext; import org.elasticsearch.search.aggregations.support.ValuesSource; import org.elasticsearch.search.aggregations.support.ValuesSourceAggregatorFactory; import org.elasticsearch.search.aggregations.support.ValuesSourceConfig; +import org.elasticsearch.search.aggregations.support.format.ValueFormatter; import java.io.IOException; import java.util.Map; @@ -44,8 +46,10 @@ public class MinAggregator extends NumericMetricsAggregator.SingleValue { private NumericDoubleValues values; private DoubleArray mins; + private ValueFormatter formatter; - public MinAggregator(String name, long estimatedBucketsCount, ValuesSource.Numeric valuesSource, AggregationContext context, Aggregator parent, Map metaData) { + public MinAggregator(String name, long estimatedBucketsCount, ValuesSource.Numeric valuesSource, @Nullable ValueFormatter formatter, + AggregationContext context, Aggregator parent, Map metaData) { super(name, estimatedBucketsCount, context, parent, metaData); this.valuesSource = valuesSource; if (valuesSource != null) { @@ -53,6 +57,7 @@ public class MinAggregator extends NumericMetricsAggregator.SingleValue { mins = bigArrays.newDoubleArray(initialSize, false); mins.fill(0, mins.size(), Double.POSITIVE_INFINITY); } + this.formatter = formatter; } @Override @@ -87,15 +92,15 @@ public class MinAggregator extends NumericMetricsAggregator.SingleValue { @Override public InternalAggregation buildAggregation(long owningBucketOrdinal) { if (valuesSource == null) { - return new InternalMin(name, Double.POSITIVE_INFINITY, getMetaData()); + return new InternalMin(name, Double.POSITIVE_INFINITY, formatter, getMetaData()); } assert owningBucketOrdinal < mins.size(); - return new InternalMin(name, mins.get(owningBucketOrdinal), getMetaData()); + return new InternalMin(name, mins.get(owningBucketOrdinal), formatter, getMetaData()); } @Override public InternalAggregation buildEmptyAggregation() { - return new InternalMin(name, Double.POSITIVE_INFINITY, getMetaData()); + return new InternalMin(name, Double.POSITIVE_INFINITY, formatter, getMetaData()); } public static class Factory extends ValuesSourceAggregatorFactory.LeafOnly> { @@ -106,12 +111,12 @@ public class MinAggregator extends NumericMetricsAggregator.SingleValue { @Override protected Aggregator createUnmapped(AggregationContext aggregationContext, Aggregator parent, Map metaData) { - return new MinAggregator(name, 0, null, aggregationContext, parent, metaData); + return new MinAggregator(name, 0, null, config.formatter(), aggregationContext, parent, metaData); } @Override protected Aggregator create(ValuesSource.Numeric valuesSource, long expectedBucketsCount, AggregationContext aggregationContext, Aggregator parent, Map metaData) { - return new MinAggregator(name, expectedBucketsCount, valuesSource, aggregationContext, parent, metaData); + return new MinAggregator(name, expectedBucketsCount, valuesSource, config.formatter(), aggregationContext, parent, metaData); } } diff --git a/src/main/java/org/elasticsearch/search/aggregations/metrics/percentiles/AbstractInternalPercentiles.java b/src/main/java/org/elasticsearch/search/aggregations/metrics/percentiles/AbstractInternalPercentiles.java index 7adf7e4b1c5..67f33934bf6 100644 --- a/src/main/java/org/elasticsearch/search/aggregations/metrics/percentiles/AbstractInternalPercentiles.java +++ b/src/main/java/org/elasticsearch/search/aggregations/metrics/percentiles/AbstractInternalPercentiles.java @@ -21,12 +21,14 @@ package org.elasticsearch.search.aggregations.metrics.percentiles; import org.elasticsearch.ElasticsearchIllegalArgumentException; import org.elasticsearch.Version; +import org.elasticsearch.common.inject.internal.Nullable; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.search.aggregations.InternalAggregation; import org.elasticsearch.search.aggregations.metrics.InternalNumericMetricsAggregation; import org.elasticsearch.search.aggregations.metrics.percentiles.tdigest.TDigestState; +import org.elasticsearch.search.aggregations.support.format.ValueFormatter; import org.elasticsearch.search.aggregations.support.format.ValueFormatterStreams; import java.io.IOException; @@ -41,11 +43,13 @@ abstract class AbstractInternalPercentiles extends InternalNumericMetricsAggrega AbstractInternalPercentiles() {} // for serialization - public AbstractInternalPercentiles(String name, double[] keys, TDigestState state, boolean keyed, Map metaData) { + public AbstractInternalPercentiles(String name, double[] keys, TDigestState state, boolean keyed, @Nullable ValueFormatter formatter, + Map metaData) { super(name, metaData); this.keys = keys; this.state = state; this.keyed = keyed; + this.valueFormatter = formatter; } @Override diff --git a/src/main/java/org/elasticsearch/search/aggregations/metrics/percentiles/AbstractPercentilesAggregator.java b/src/main/java/org/elasticsearch/search/aggregations/metrics/percentiles/AbstractPercentilesAggregator.java index 6cae6568d52..82dbba6dccc 100644 --- a/src/main/java/org/elasticsearch/search/aggregations/metrics/percentiles/AbstractPercentilesAggregator.java +++ b/src/main/java/org/elasticsearch/search/aggregations/metrics/percentiles/AbstractPercentilesAggregator.java @@ -20,6 +20,7 @@ package org.elasticsearch.search.aggregations.metrics.percentiles; import org.apache.lucene.index.LeafReaderContext; +import org.elasticsearch.common.inject.internal.Nullable; import org.elasticsearch.common.lease.Releasables; import org.elasticsearch.common.util.ArrayUtils; import org.elasticsearch.common.util.ObjectArray; @@ -29,6 +30,7 @@ import org.elasticsearch.search.aggregations.metrics.NumericMetricsAggregator; import org.elasticsearch.search.aggregations.metrics.percentiles.tdigest.TDigestState; import org.elasticsearch.search.aggregations.support.AggregationContext; import org.elasticsearch.search.aggregations.support.ValuesSource; +import org.elasticsearch.search.aggregations.support.format.ValueFormatter; import java.io.IOException; import java.util.Map; @@ -45,12 +47,15 @@ public abstract class AbstractPercentilesAggregator extends NumericMetricsAggreg protected ObjectArray states; protected final double compression; protected final boolean keyed; + protected ValueFormatter formatter; public AbstractPercentilesAggregator(String name, long estimatedBucketsCount, ValuesSource.Numeric valuesSource, AggregationContext context, - Aggregator parent, double[] keys, double compression, boolean keyed, Map metaData) { + Aggregator parent, double[] keys, double compression, boolean keyed, + @Nullable ValueFormatter formatter, Map metaData) { super(name, estimatedBucketsCount, context, parent, metaData); this.valuesSource = valuesSource; this.keyed = keyed; + this.formatter = formatter; this.states = bigArrays.newObjectArray(estimatedBucketsCount); this.keys = keys; this.compression = compression; diff --git a/src/main/java/org/elasticsearch/search/aggregations/metrics/percentiles/AbstractPercentilesParser.java b/src/main/java/org/elasticsearch/search/aggregations/metrics/percentiles/AbstractPercentilesParser.java index 6f62b8c457b..7fee395966b 100644 --- a/src/main/java/org/elasticsearch/search/aggregations/metrics/percentiles/AbstractPercentilesParser.java +++ b/src/main/java/org/elasticsearch/search/aggregations/metrics/percentiles/AbstractPercentilesParser.java @@ -20,6 +20,7 @@ package org.elasticsearch.search.aggregations.metrics.percentiles; import com.carrotsearch.hppc.DoubleArrayList; + import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.search.SearchParseException; import org.elasticsearch.search.aggregations.Aggregator; @@ -35,14 +36,17 @@ import java.util.Arrays; public abstract class AbstractPercentilesParser implements Aggregator.Parser { - public AbstractPercentilesParser() { - super(); + private boolean formattable; + + public AbstractPercentilesParser(boolean formattable) { + this.formattable = formattable; } @Override public AggregatorFactory parse(String aggregationName, XContentParser parser, SearchContext context) throws IOException { - ValuesSourceParser vsParser = ValuesSourceParser.numeric(aggregationName, InternalPercentiles.TYPE, context).build(); + ValuesSourceParser vsParser = ValuesSourceParser.numeric(aggregationName, InternalPercentiles.TYPE, context) + .formattable(formattable).build(); double[] keys = null; boolean keyed = true; diff --git a/src/main/java/org/elasticsearch/search/aggregations/metrics/percentiles/InternalPercentileRanks.java b/src/main/java/org/elasticsearch/search/aggregations/metrics/percentiles/InternalPercentileRanks.java index 008f0ca7cb4..190ca363ed3 100644 --- a/src/main/java/org/elasticsearch/search/aggregations/metrics/percentiles/InternalPercentileRanks.java +++ b/src/main/java/org/elasticsearch/search/aggregations/metrics/percentiles/InternalPercentileRanks.java @@ -19,9 +19,12 @@ package org.elasticsearch.search.aggregations.metrics.percentiles; import com.google.common.collect.UnmodifiableIterator; + +import org.elasticsearch.common.inject.internal.Nullable; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.search.aggregations.AggregationStreams; import org.elasticsearch.search.aggregations.metrics.percentiles.tdigest.TDigestState; +import org.elasticsearch.search.aggregations.support.format.ValueFormatter; import java.io.IOException; import java.util.Iterator; @@ -49,8 +52,9 @@ public class InternalPercentileRanks extends AbstractInternalPercentiles impleme InternalPercentileRanks() {} // for serialization - public InternalPercentileRanks(String name, double[] cdfValues, TDigestState state, boolean keyed, Map metaData) { - super(name, cdfValues, state, keyed, metaData); + public InternalPercentileRanks(String name, double[] cdfValues, TDigestState state, boolean keyed, @Nullable ValueFormatter formatter, + Map metaData) { + super(name, cdfValues, state, keyed, formatter, metaData); } @Override @@ -63,13 +67,18 @@ public class InternalPercentileRanks extends AbstractInternalPercentiles impleme return percentileRank(state, value); } + @Override + public String percentAsString(double value) { + return valueAsString(String.valueOf(value)); + } + @Override public double value(double key) { return percent(key); } protected AbstractInternalPercentiles createReduced(String name, double[] keys, TDigestState merged, boolean keyed, Map metaData) { - return new InternalPercentileRanks(name, keys, merged, keyed, metaData); + return new InternalPercentileRanks(name, keys, merged, keyed, valueFormatter, metaData); } @Override diff --git a/src/main/java/org/elasticsearch/search/aggregations/metrics/percentiles/InternalPercentiles.java b/src/main/java/org/elasticsearch/search/aggregations/metrics/percentiles/InternalPercentiles.java index d7171ecb55b..5e7d47803d8 100644 --- a/src/main/java/org/elasticsearch/search/aggregations/metrics/percentiles/InternalPercentiles.java +++ b/src/main/java/org/elasticsearch/search/aggregations/metrics/percentiles/InternalPercentiles.java @@ -19,9 +19,12 @@ package org.elasticsearch.search.aggregations.metrics.percentiles; import com.google.common.collect.UnmodifiableIterator; + +import org.elasticsearch.common.inject.internal.Nullable; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.search.aggregations.AggregationStreams; import org.elasticsearch.search.aggregations.metrics.percentiles.tdigest.TDigestState; +import org.elasticsearch.search.aggregations.support.format.ValueFormatter; import java.io.IOException; import java.util.Iterator; @@ -49,8 +52,9 @@ public class InternalPercentiles extends AbstractInternalPercentiles implements InternalPercentiles() {} // for serialization - public InternalPercentiles(String name, double[] percents, TDigestState state, boolean keyed, Map metaData) { - super(name, percents, state, keyed, metaData); + public InternalPercentiles(String name, double[] percents, TDigestState state, boolean keyed, @Nullable ValueFormatter formatter, + Map metaData) { + super(name, percents, state, keyed, formatter, metaData); } @Override @@ -63,13 +67,18 @@ public class InternalPercentiles extends AbstractInternalPercentiles implements return state.quantile(percent / 100); } + @Override + public String percentileAsString(double percent) { + return valueAsString(String.valueOf(percent)); + } + @Override public double value(double key) { return percentile(key); } protected AbstractInternalPercentiles createReduced(String name, double[] keys, TDigestState merged, boolean keyed, Map metaData) { - return new InternalPercentiles(name, keys, merged, keyed, metaData); + return new InternalPercentiles(name, keys, merged, keyed, valueFormatter, metaData); } @Override diff --git a/src/main/java/org/elasticsearch/search/aggregations/metrics/percentiles/PercentileRanks.java b/src/main/java/org/elasticsearch/search/aggregations/metrics/percentiles/PercentileRanks.java index 47d63540256..a0f04c91d37 100644 --- a/src/main/java/org/elasticsearch/search/aggregations/metrics/percentiles/PercentileRanks.java +++ b/src/main/java/org/elasticsearch/search/aggregations/metrics/percentiles/PercentileRanks.java @@ -19,15 +19,20 @@ package org.elasticsearch.search.aggregations.metrics.percentiles; -import org.elasticsearch.search.aggregations.Aggregation; +import org.elasticsearch.search.aggregations.metrics.NumericMetricsAggregation; /** * An aggregation that computes approximate percentiles given values. */ -public interface PercentileRanks extends Aggregation, Iterable{ +public interface PercentileRanks extends NumericMetricsAggregation.MultiValue, Iterable { /** * Return the percentile for the given value. */ double percent(double value); + + /** + * Return the percentile for the given value as a String. + */ + String percentAsString(double value); } diff --git a/src/main/java/org/elasticsearch/search/aggregations/metrics/percentiles/PercentileRanksAggregator.java b/src/main/java/org/elasticsearch/search/aggregations/metrics/percentiles/PercentileRanksAggregator.java index a53511fbfc2..07dfcae9f64 100644 --- a/src/main/java/org/elasticsearch/search/aggregations/metrics/percentiles/PercentileRanksAggregator.java +++ b/src/main/java/org/elasticsearch/search/aggregations/metrics/percentiles/PercentileRanksAggregator.java @@ -18,11 +18,16 @@ */ package org.elasticsearch.search.aggregations.metrics.percentiles; +import org.elasticsearch.common.inject.internal.Nullable; import org.elasticsearch.search.aggregations.Aggregator; import org.elasticsearch.search.aggregations.InternalAggregation; import org.elasticsearch.search.aggregations.metrics.percentiles.tdigest.TDigestState; -import org.elasticsearch.search.aggregations.support.*; +import org.elasticsearch.search.aggregations.support.AggregationContext; +import org.elasticsearch.search.aggregations.support.ValuesSource; import org.elasticsearch.search.aggregations.support.ValuesSource.Numeric; +import org.elasticsearch.search.aggregations.support.ValuesSourceAggregatorFactory; +import org.elasticsearch.search.aggregations.support.ValuesSourceConfig; +import org.elasticsearch.search.aggregations.support.format.ValueFormatter; import java.util.Map; @@ -32,8 +37,9 @@ import java.util.Map; public class PercentileRanksAggregator extends AbstractPercentilesAggregator { public PercentileRanksAggregator(String name, long estimatedBucketsCount, Numeric valuesSource, AggregationContext context, - Aggregator parent, double[] percents, double compression, boolean keyed, Map metaData) { - super(name, estimatedBucketsCount, valuesSource, context, parent, percents, compression, keyed, metaData); + Aggregator parent, double[] percents, double compression, boolean keyed, @Nullable ValueFormatter formatter, + Map metaData) { + super(name, estimatedBucketsCount, valuesSource, context, parent, percents, compression, keyed, formatter, metaData); } @Override @@ -42,13 +48,13 @@ public class PercentileRanksAggregator extends AbstractPercentilesAggregator { if (state == null) { return buildEmptyAggregation(); } else { - return new InternalPercentileRanks(name, keys, state, keyed, getMetaData()); + return new InternalPercentileRanks(name, keys, state, keyed, formatter, getMetaData()); } } @Override public InternalAggregation buildEmptyAggregation() { - return new InternalPercentileRanks(name, keys, new TDigestState(compression), keyed, getMetaData()); + return new InternalPercentileRanks(name, keys, new TDigestState(compression), keyed, formatter, getMetaData()); } @Override @@ -77,12 +83,14 @@ public class PercentileRanksAggregator extends AbstractPercentilesAggregator { @Override protected Aggregator createUnmapped(AggregationContext aggregationContext, Aggregator parent, Map metaData) { - return new PercentileRanksAggregator(name, 0, null, aggregationContext, parent, values, compression, keyed, metaData); + return new PercentileRanksAggregator(name, 0, null, aggregationContext, parent, values, compression, keyed, config.formatter(), + metaData); } @Override protected Aggregator create(ValuesSource.Numeric valuesSource, long expectedBucketsCount, AggregationContext aggregationContext, Aggregator parent, Map metaData) { - return new PercentileRanksAggregator(name, expectedBucketsCount, valuesSource, aggregationContext, parent, values, compression, keyed, metaData); + return new PercentileRanksAggregator(name, expectedBucketsCount, valuesSource, aggregationContext, parent, values, compression, + keyed, config.formatter(), metaData); } } } diff --git a/src/main/java/org/elasticsearch/search/aggregations/metrics/percentiles/PercentileRanksParser.java b/src/main/java/org/elasticsearch/search/aggregations/metrics/percentiles/PercentileRanksParser.java index 11124028d8e..4018aac6f71 100644 --- a/src/main/java/org/elasticsearch/search/aggregations/metrics/percentiles/PercentileRanksParser.java +++ b/src/main/java/org/elasticsearch/search/aggregations/metrics/percentiles/PercentileRanksParser.java @@ -29,6 +29,10 @@ import org.elasticsearch.search.internal.SearchContext; */ public class PercentileRanksParser extends AbstractPercentilesParser { + public PercentileRanksParser() { + super(false); + } + @Override public String type() { return InternalPercentileRanks.TYPE.name(); diff --git a/src/main/java/org/elasticsearch/search/aggregations/metrics/percentiles/Percentiles.java b/src/main/java/org/elasticsearch/search/aggregations/metrics/percentiles/Percentiles.java index b2b10c785c8..b753dd1cf5d 100644 --- a/src/main/java/org/elasticsearch/search/aggregations/metrics/percentiles/Percentiles.java +++ b/src/main/java/org/elasticsearch/search/aggregations/metrics/percentiles/Percentiles.java @@ -18,16 +18,21 @@ */ package org.elasticsearch.search.aggregations.metrics.percentiles; -import org.elasticsearch.search.aggregations.Aggregation; +import org.elasticsearch.search.aggregations.metrics.NumericMetricsAggregation; /** * An aggregation that computes approximate percentiles. */ -public interface Percentiles extends Aggregation, Iterable { +public interface Percentiles extends NumericMetricsAggregation.MultiValue, Iterable { /** * Return the value associated with the provided percentile. */ double percentile(double percent); + /** + * Return the value associated with the provided percentile as a String. + */ + String percentileAsString(double percent); + } diff --git a/src/main/java/org/elasticsearch/search/aggregations/metrics/percentiles/PercentilesAggregator.java b/src/main/java/org/elasticsearch/search/aggregations/metrics/percentiles/PercentilesAggregator.java index b1177ea2d57..b34fc7f2129 100644 --- a/src/main/java/org/elasticsearch/search/aggregations/metrics/percentiles/PercentilesAggregator.java +++ b/src/main/java/org/elasticsearch/search/aggregations/metrics/percentiles/PercentilesAggregator.java @@ -18,11 +18,16 @@ */ package org.elasticsearch.search.aggregations.metrics.percentiles; +import org.elasticsearch.common.inject.internal.Nullable; import org.elasticsearch.search.aggregations.Aggregator; import org.elasticsearch.search.aggregations.InternalAggregation; import org.elasticsearch.search.aggregations.metrics.percentiles.tdigest.TDigestState; -import org.elasticsearch.search.aggregations.support.*; +import org.elasticsearch.search.aggregations.support.AggregationContext; +import org.elasticsearch.search.aggregations.support.ValuesSource; import org.elasticsearch.search.aggregations.support.ValuesSource.Numeric; +import org.elasticsearch.search.aggregations.support.ValuesSourceAggregatorFactory; +import org.elasticsearch.search.aggregations.support.ValuesSourceConfig; +import org.elasticsearch.search.aggregations.support.format.ValueFormatter; import java.util.Map; @@ -32,8 +37,9 @@ import java.util.Map; public class PercentilesAggregator extends AbstractPercentilesAggregator { public PercentilesAggregator(String name, long estimatedBucketsCount, Numeric valuesSource, AggregationContext context, - Aggregator parent, double[] percents, double compression, boolean keyed, Map metaData) { - super(name, estimatedBucketsCount, valuesSource, context, parent, percents, compression, keyed, metaData); + Aggregator parent, double[] percents, double compression, boolean keyed, @Nullable ValueFormatter formatter, + Map metaData) { + super(name, estimatedBucketsCount, valuesSource, context, parent, percents, compression, keyed, formatter, metaData); } @Override @@ -42,7 +48,7 @@ public class PercentilesAggregator extends AbstractPercentilesAggregator { if (state == null) { return buildEmptyAggregation(); } else { - return new InternalPercentiles(name, keys, state, keyed, getMetaData()); + return new InternalPercentiles(name, keys, state, keyed, formatter, getMetaData()); } } @@ -58,7 +64,7 @@ public class PercentilesAggregator extends AbstractPercentilesAggregator { @Override public InternalAggregation buildEmptyAggregation() { - return new InternalPercentiles(name, keys, new TDigestState(compression), keyed, getMetaData()); + return new InternalPercentiles(name, keys, new TDigestState(compression), keyed, formatter, getMetaData()); } public static class Factory extends ValuesSourceAggregatorFactory.LeafOnly> { @@ -77,12 +83,14 @@ public class PercentilesAggregator extends AbstractPercentilesAggregator { @Override protected Aggregator createUnmapped(AggregationContext aggregationContext, Aggregator parent, Map metaData) { - return new PercentilesAggregator(name, 0, null, aggregationContext, parent, percents, compression, keyed, metaData); + return new PercentilesAggregator(name, 0, null, aggregationContext, parent, percents, compression, keyed, config.formatter(), + metaData); } @Override protected Aggregator create(ValuesSource.Numeric valuesSource, long expectedBucketsCount, AggregationContext aggregationContext, Aggregator parent, Map metaData) { - return new PercentilesAggregator(name, expectedBucketsCount, valuesSource, aggregationContext, parent, percents, compression, keyed, metaData); + return new PercentilesAggregator(name, expectedBucketsCount, valuesSource, aggregationContext, parent, percents, compression, + keyed, config.formatter(), metaData); } } } diff --git a/src/main/java/org/elasticsearch/search/aggregations/metrics/percentiles/PercentilesParser.java b/src/main/java/org/elasticsearch/search/aggregations/metrics/percentiles/PercentilesParser.java index e5c5a307ee8..f3b186c5063 100644 --- a/src/main/java/org/elasticsearch/search/aggregations/metrics/percentiles/PercentilesParser.java +++ b/src/main/java/org/elasticsearch/search/aggregations/metrics/percentiles/PercentilesParser.java @@ -28,6 +28,10 @@ import org.elasticsearch.search.internal.SearchContext; */ public class PercentilesParser extends AbstractPercentilesParser { + public PercentilesParser() { + super(true); + } + private final static double[] DEFAULT_PERCENTS = new double[] { 1, 5, 25, 50, 75, 95, 99 }; @Override diff --git a/src/main/java/org/elasticsearch/search/aggregations/metrics/stats/InternalStats.java b/src/main/java/org/elasticsearch/search/aggregations/metrics/stats/InternalStats.java index df517a1fd31..86bda11cd8e 100644 --- a/src/main/java/org/elasticsearch/search/aggregations/metrics/stats/InternalStats.java +++ b/src/main/java/org/elasticsearch/search/aggregations/metrics/stats/InternalStats.java @@ -18,6 +18,7 @@ */ package org.elasticsearch.search.aggregations.metrics.stats; +import org.elasticsearch.common.inject.internal.Nullable; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; import org.elasticsearch.common.xcontent.XContentBuilder; @@ -25,6 +26,7 @@ import org.elasticsearch.common.xcontent.XContentBuilderString; import org.elasticsearch.search.aggregations.AggregationStreams; import org.elasticsearch.search.aggregations.InternalAggregation; import org.elasticsearch.search.aggregations.metrics.InternalNumericMetricsAggregation; +import org.elasticsearch.search.aggregations.support.format.ValueFormatter; import org.elasticsearch.search.aggregations.support.format.ValueFormatterStreams; import java.io.IOException; @@ -66,12 +68,14 @@ public class InternalStats extends InternalNumericMetricsAggregation.MultiValue protected InternalStats() {} // for serialization - public InternalStats(String name, long count, double sum, double min, double max, Map metaData) { + public InternalStats(String name, long count, double sum, double min, double max, @Nullable ValueFormatter formatter, + Map metaData) { super(name, metaData); this.count = count; this.sum = sum; this.min = min; this.max = max; + this.valueFormatter = formatter; } @Override @@ -99,6 +103,31 @@ public class InternalStats extends InternalNumericMetricsAggregation.MultiValue return sum; } + @Override + public String getCountAsString() { + return valueAsString(Metrics.count.name()); + } + + @Override + public String getMinAsString() { + return valueAsString(Metrics.min.name()); + } + + @Override + public String getMaxAsString() { + return valueAsString(Metrics.max.name()); + } + + @Override + public String getAvgAsString() { + return valueAsString(Metrics.avg.name()); + } + + @Override + public String getSumAsString() { + return valueAsString(Metrics.sum.name()); + } + @Override public Type type() { return TYPE; @@ -131,7 +160,7 @@ public class InternalStats extends InternalNumericMetricsAggregation.MultiValue max = Math.max(max, stats.getMax()); sum += stats.getSum(); } - return new InternalStats(name, count, sum, min, max, getMetaData()); + return new InternalStats(name, count, sum, min, max, valueFormatter, getMetaData()); } @Override diff --git a/src/main/java/org/elasticsearch/search/aggregations/metrics/stats/Stats.java b/src/main/java/org/elasticsearch/search/aggregations/metrics/stats/Stats.java index b093c59562c..4910dc14002 100644 --- a/src/main/java/org/elasticsearch/search/aggregations/metrics/stats/Stats.java +++ b/src/main/java/org/elasticsearch/search/aggregations/metrics/stats/Stats.java @@ -18,15 +18,15 @@ */ package org.elasticsearch.search.aggregations.metrics.stats; -import org.elasticsearch.search.aggregations.Aggregation; +import org.elasticsearch.search.aggregations.metrics.NumericMetricsAggregation; /** * Statistics over a set of values (either aggregated over field data or scripts) */ -public interface Stats extends Aggregation { +public interface Stats extends NumericMetricsAggregation.MultiValue { /** - * @return The number of values that were aggregated + * @return The number of values that were aggregated. */ long getCount(); @@ -50,4 +50,29 @@ public interface Stats extends Aggregation { */ double getSum(); + /** + * @return The number of values that were aggregated as a String. + */ + String getCountAsString(); + + /** + * @return The minimum value of all aggregated values as a String. + */ + String getMinAsString(); + + /** + * @return The maximum value of all aggregated values as a String. + */ + String getMaxAsString(); + + /** + * @return The avg value over all aggregated values as a String. + */ + String getAvgAsString(); + + /** + * @return The sum of aggregated values as a String. + */ + String getSumAsString(); + } diff --git a/src/main/java/org/elasticsearch/search/aggregations/metrics/stats/StatsAggegator.java b/src/main/java/org/elasticsearch/search/aggregations/metrics/stats/StatsAggegator.java index 7bce48e92a0..980d808dcad 100644 --- a/src/main/java/org/elasticsearch/search/aggregations/metrics/stats/StatsAggegator.java +++ b/src/main/java/org/elasticsearch/search/aggregations/metrics/stats/StatsAggegator.java @@ -20,6 +20,7 @@ package org.elasticsearch.search.aggregations.metrics.stats; import org.apache.lucene.index.LeafReaderContext; import org.elasticsearch.ElasticsearchIllegalArgumentException; +import org.elasticsearch.common.inject.internal.Nullable; import org.elasticsearch.common.lease.Releasables; import org.elasticsearch.common.util.BigArrays; import org.elasticsearch.common.util.DoubleArray; @@ -32,6 +33,7 @@ import org.elasticsearch.search.aggregations.support.AggregationContext; import org.elasticsearch.search.aggregations.support.ValuesSource; import org.elasticsearch.search.aggregations.support.ValuesSourceAggregatorFactory; import org.elasticsearch.search.aggregations.support.ValuesSourceConfig; +import org.elasticsearch.search.aggregations.support.format.ValueFormatter; import java.io.IOException; import java.util.Map; @@ -48,8 +50,10 @@ public class StatsAggegator extends NumericMetricsAggregator.MultiValue { private DoubleArray sums; private DoubleArray mins; private DoubleArray maxes; + private ValueFormatter formatter; - public StatsAggegator(String name, long estimatedBucketsCount, ValuesSource.Numeric valuesSource, AggregationContext context, Aggregator parent, Map metaData) { + public StatsAggegator(String name, long estimatedBucketsCount, ValuesSource.Numeric valuesSource, @Nullable ValueFormatter formatter, + AggregationContext context, Aggregator parent, Map metaData) { super(name, estimatedBucketsCount, context, parent, metaData); this.valuesSource = valuesSource; if (valuesSource != null) { @@ -61,6 +65,7 @@ public class StatsAggegator extends NumericMetricsAggregator.MultiValue { maxes = bigArrays.newDoubleArray(initialSize, false); maxes.fill(0, maxes.size(), Double.NEGATIVE_INFINITY); } + this.formatter = formatter; } @Override @@ -129,15 +134,16 @@ public class StatsAggegator extends NumericMetricsAggregator.MultiValue { @Override public InternalAggregation buildAggregation(long owningBucketOrdinal) { if (valuesSource == null) { - return new InternalStats(name, 0, 0, Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY, getMetaData()); + return new InternalStats(name, 0, 0, Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY, formatter, getMetaData()); } assert owningBucketOrdinal < counts.size(); - return new InternalStats(name, counts.get(owningBucketOrdinal), sums.get(owningBucketOrdinal), mins.get(owningBucketOrdinal), maxes.get(owningBucketOrdinal), getMetaData()); + return new InternalStats(name, counts.get(owningBucketOrdinal), sums.get(owningBucketOrdinal), mins.get(owningBucketOrdinal), + maxes.get(owningBucketOrdinal), formatter, getMetaData()); } @Override public InternalAggregation buildEmptyAggregation() { - return new InternalStats(name, 0, 0, Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY, getMetaData()); + return new InternalStats(name, 0, 0, Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY, formatter, getMetaData()); } public static class Factory extends ValuesSourceAggregatorFactory.LeafOnly> { @@ -148,12 +154,12 @@ public class StatsAggegator extends NumericMetricsAggregator.MultiValue { @Override protected Aggregator createUnmapped(AggregationContext aggregationContext, Aggregator parent, Map metaData) { - return new StatsAggegator(name, 0, null, aggregationContext, parent, metaData); + return new StatsAggegator(name, 0, null, config.formatter(), aggregationContext, parent, metaData); } @Override protected Aggregator create(ValuesSource.Numeric valuesSource, long expectedBucketsCount, AggregationContext aggregationContext, Aggregator parent, Map metaData) { - return new StatsAggegator(name, expectedBucketsCount, valuesSource, aggregationContext, parent, metaData); + return new StatsAggegator(name, expectedBucketsCount, valuesSource, config.formatter(), aggregationContext, parent, metaData); } } diff --git a/src/main/java/org/elasticsearch/search/aggregations/metrics/stats/extended/ExtendedStats.java b/src/main/java/org/elasticsearch/search/aggregations/metrics/stats/extended/ExtendedStats.java index 4a776ace4ed..9fe541a785d 100644 --- a/src/main/java/org/elasticsearch/search/aggregations/metrics/stats/extended/ExtendedStats.java +++ b/src/main/java/org/elasticsearch/search/aggregations/metrics/stats/extended/ExtendedStats.java @@ -40,4 +40,19 @@ public interface ExtendedStats extends Stats { */ double getStdDeviation(); + /** + * The sum of the squares of the collected values as a String. + */ + String getSumOfSquaresAsString(); + + /** + * The variance of the collected values as a String. + */ + String getVarianceAsString(); + + /** + * The standard deviation of the collected values as a String. + */ + String getStdDeviationAsString(); + } diff --git a/src/main/java/org/elasticsearch/search/aggregations/metrics/stats/extended/ExtendedStatsAggregator.java b/src/main/java/org/elasticsearch/search/aggregations/metrics/stats/extended/ExtendedStatsAggregator.java index df531c869b2..e8a4b7e008a 100644 --- a/src/main/java/org/elasticsearch/search/aggregations/metrics/stats/extended/ExtendedStatsAggregator.java +++ b/src/main/java/org/elasticsearch/search/aggregations/metrics/stats/extended/ExtendedStatsAggregator.java @@ -20,6 +20,7 @@ package org.elasticsearch.search.aggregations.metrics.stats.extended; import org.apache.lucene.index.LeafReaderContext; import org.elasticsearch.ElasticsearchIllegalArgumentException; +import org.elasticsearch.common.inject.internal.Nullable; import org.elasticsearch.common.lease.Releasables; import org.elasticsearch.common.util.BigArrays; import org.elasticsearch.common.util.DoubleArray; @@ -32,6 +33,7 @@ import org.elasticsearch.search.aggregations.support.AggregationContext; import org.elasticsearch.search.aggregations.support.ValuesSource; import org.elasticsearch.search.aggregations.support.ValuesSourceAggregatorFactory; import org.elasticsearch.search.aggregations.support.ValuesSourceConfig; +import org.elasticsearch.search.aggregations.support.format.ValueFormatter; import java.io.IOException; import java.util.Map; @@ -49,10 +51,13 @@ public class ExtendedStatsAggregator extends NumericMetricsAggregator.MultiValue private DoubleArray mins; private DoubleArray maxes; private DoubleArray sumOfSqrs; + private ValueFormatter formatter; - public ExtendedStatsAggregator(String name, long estimatedBucketsCount, ValuesSource.Numeric valuesSource, AggregationContext context, Aggregator parent, Map metaData) { + public ExtendedStatsAggregator(String name, long estimatedBucketsCount, ValuesSource.Numeric valuesSource, + @Nullable ValueFormatter formatter, AggregationContext context, Aggregator parent, Map metaData) { super(name, estimatedBucketsCount, context, parent, metaData); this.valuesSource = valuesSource; + this.formatter = formatter; if (valuesSource != null) { final long initialSize = estimatedBucketsCount < 2 ? 1 : estimatedBucketsCount; counts = bigArrays.newLongArray(initialSize, true); @@ -144,16 +149,16 @@ public class ExtendedStatsAggregator extends NumericMetricsAggregator.MultiValue @Override public InternalAggregation buildAggregation(long owningBucketOrdinal) { if (valuesSource == null) { - return new InternalExtendedStats(name, 0, 0d, Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY, 0d, getMetaData()); + return new InternalExtendedStats(name, 0, 0d, Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY, 0d, formatter, getMetaData()); } assert owningBucketOrdinal < counts.size(); - return new InternalExtendedStats(name, counts.get(owningBucketOrdinal), sums.get(owningBucketOrdinal), mins.get(owningBucketOrdinal), - maxes.get(owningBucketOrdinal), sumOfSqrs.get(owningBucketOrdinal), getMetaData()); + return new InternalExtendedStats(name, counts.get(owningBucketOrdinal), sums.get(owningBucketOrdinal), + mins.get(owningBucketOrdinal), maxes.get(owningBucketOrdinal), sumOfSqrs.get(owningBucketOrdinal), formatter, getMetaData()); } @Override public InternalAggregation buildEmptyAggregation() { - return new InternalExtendedStats(name, 0, 0d, Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY, 0d, getMetaData()); + return new InternalExtendedStats(name, 0, 0d, Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY, 0d, formatter, getMetaData()); } @Override @@ -169,12 +174,13 @@ public class ExtendedStatsAggregator extends NumericMetricsAggregator.MultiValue @Override protected Aggregator createUnmapped(AggregationContext aggregationContext, Aggregator parent, Map metaData) { - return new ExtendedStatsAggregator(name, 0, null, aggregationContext, parent, metaData); + return new ExtendedStatsAggregator(name, 0, null, config.formatter(), aggregationContext, parent, metaData); } @Override protected Aggregator create(ValuesSource.Numeric valuesSource, long expectedBucketsCount, AggregationContext aggregationContext, Aggregator parent, Map metaData) { - return new ExtendedStatsAggregator(name, expectedBucketsCount, valuesSource, aggregationContext, parent, metaData); + return new ExtendedStatsAggregator(name, expectedBucketsCount, valuesSource, config.formatter(), aggregationContext, parent, + metaData); } } } diff --git a/src/main/java/org/elasticsearch/search/aggregations/metrics/stats/extended/InternalExtendedStats.java b/src/main/java/org/elasticsearch/search/aggregations/metrics/stats/extended/InternalExtendedStats.java index 5a258a4f9de..2f02d3d21c7 100644 --- a/src/main/java/org/elasticsearch/search/aggregations/metrics/stats/extended/InternalExtendedStats.java +++ b/src/main/java/org/elasticsearch/search/aggregations/metrics/stats/extended/InternalExtendedStats.java @@ -18,6 +18,7 @@ */ package org.elasticsearch.search.aggregations.metrics.stats.extended; +import org.elasticsearch.common.inject.internal.Nullable; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; import org.elasticsearch.common.xcontent.XContentBuilder; @@ -25,6 +26,7 @@ import org.elasticsearch.common.xcontent.XContentBuilderString; import org.elasticsearch.search.aggregations.AggregationStreams; import org.elasticsearch.search.aggregations.InternalAggregation; import org.elasticsearch.search.aggregations.metrics.stats.InternalStats; +import org.elasticsearch.search.aggregations.support.format.ValueFormatter; import java.io.IOException; import java.util.Map; @@ -62,8 +64,9 @@ public class InternalExtendedStats extends InternalStats implements ExtendedStat InternalExtendedStats() {} // for serialization - public InternalExtendedStats(String name, long count, double sum, double min, double max, double sumOfSqrs, Map metaData) { - super(name, count, sum, min, max, metaData); + public InternalExtendedStats(String name, long count, double sum, double min, double max, double sumOfSqrs, + @Nullable ValueFormatter formatter, Map metaData) { + super(name, count, sum, min, max, formatter, metaData); this.sumOfSqrs = sumOfSqrs; } @@ -101,6 +104,21 @@ public class InternalExtendedStats extends InternalStats implements ExtendedStat return Math.sqrt(getVariance()); } + @Override + public String getSumOfSquaresAsString() { + return valueAsString(Metrics.sum_of_squares.name()); + } + + @Override + public String getVarianceAsString() { + return valueAsString(Metrics.variance.name()); + } + + @Override + public String getStdDeviationAsString() { + return valueAsString(Metrics.std_deviation.name()); + } + @Override public InternalExtendedStats reduce(ReduceContext reduceContext) { double sumOfSqrs = 0; @@ -109,7 +127,8 @@ public class InternalExtendedStats extends InternalStats implements ExtendedStat sumOfSqrs += stats.getSumOfSquares(); } final InternalStats stats = super.reduce(reduceContext); - return new InternalExtendedStats(name, stats.getCount(), stats.getSum(), stats.getMin(), stats.getMax(), sumOfSqrs, getMetaData()); + return new InternalExtendedStats(name, stats.getCount(), stats.getSum(), stats.getMin(), stats.getMax(), sumOfSqrs, valueFormatter, + getMetaData()); } @Override diff --git a/src/main/java/org/elasticsearch/search/aggregations/metrics/sum/InternalSum.java b/src/main/java/org/elasticsearch/search/aggregations/metrics/sum/InternalSum.java index 072980561fc..b16663db26a 100644 --- a/src/main/java/org/elasticsearch/search/aggregations/metrics/sum/InternalSum.java +++ b/src/main/java/org/elasticsearch/search/aggregations/metrics/sum/InternalSum.java @@ -18,12 +18,14 @@ */ package org.elasticsearch.search.aggregations.metrics.sum; +import org.elasticsearch.common.inject.internal.Nullable; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.search.aggregations.AggregationStreams; import org.elasticsearch.search.aggregations.InternalAggregation; import org.elasticsearch.search.aggregations.metrics.InternalNumericMetricsAggregation; +import org.elasticsearch.search.aggregations.support.format.ValueFormatter; import org.elasticsearch.search.aggregations.support.format.ValueFormatterStreams; import java.io.IOException; @@ -53,9 +55,10 @@ public class InternalSum extends InternalNumericMetricsAggregation.SingleValue i InternalSum() {} // for serialization - InternalSum(String name, double sum, Map metaData){ + InternalSum(String name, double sum, @Nullable ValueFormatter formatter, Map metaData) { super(name, metaData); this.sum = sum; + this.valueFormatter = formatter; } @Override @@ -78,7 +81,7 @@ public class InternalSum extends InternalNumericMetricsAggregation.SingleValue i for (InternalAggregation aggregation : reduceContext.aggregations()) { sum += ((InternalSum) aggregation).sum; } - return new InternalSum(name, sum, getMetaData()); + return new InternalSum(name, sum, valueFormatter, getMetaData()); } @Override diff --git a/src/main/java/org/elasticsearch/search/aggregations/metrics/sum/Sum.java b/src/main/java/org/elasticsearch/search/aggregations/metrics/sum/Sum.java index 499bc502307..d9cacdba114 100644 --- a/src/main/java/org/elasticsearch/search/aggregations/metrics/sum/Sum.java +++ b/src/main/java/org/elasticsearch/search/aggregations/metrics/sum/Sum.java @@ -18,12 +18,12 @@ */ package org.elasticsearch.search.aggregations.metrics.sum; -import org.elasticsearch.search.aggregations.Aggregation; +import org.elasticsearch.search.aggregations.metrics.NumericMetricsAggregation; /** * An aggregation that computes the sum of the values in the current bucket. */ -public interface Sum extends Aggregation { +public interface Sum extends NumericMetricsAggregation.SingleValue { /** * The sum. diff --git a/src/main/java/org/elasticsearch/search/aggregations/metrics/sum/SumAggregator.java b/src/main/java/org/elasticsearch/search/aggregations/metrics/sum/SumAggregator.java index 5b0d6268b69..496c45719c3 100644 --- a/src/main/java/org/elasticsearch/search/aggregations/metrics/sum/SumAggregator.java +++ b/src/main/java/org/elasticsearch/search/aggregations/metrics/sum/SumAggregator.java @@ -19,6 +19,7 @@ package org.elasticsearch.search.aggregations.metrics.sum; import org.apache.lucene.index.LeafReaderContext; +import org.elasticsearch.common.inject.internal.Nullable; import org.elasticsearch.common.lease.Releasables; import org.elasticsearch.common.util.DoubleArray; import org.elasticsearch.index.fielddata.SortedNumericDoubleValues; @@ -29,6 +30,7 @@ import org.elasticsearch.search.aggregations.support.AggregationContext; import org.elasticsearch.search.aggregations.support.ValuesSource; import org.elasticsearch.search.aggregations.support.ValuesSourceAggregatorFactory; import org.elasticsearch.search.aggregations.support.ValuesSourceConfig; +import org.elasticsearch.search.aggregations.support.format.ValueFormatter; import java.io.IOException; import java.util.Map; @@ -42,10 +44,13 @@ public class SumAggregator extends NumericMetricsAggregator.SingleValue { private SortedNumericDoubleValues values; private DoubleArray sums; + private ValueFormatter formatter; - public SumAggregator(String name, long estimatedBucketsCount, ValuesSource.Numeric valuesSource, AggregationContext context, Aggregator parent, Map metaData) { + public SumAggregator(String name, long estimatedBucketsCount, ValuesSource.Numeric valuesSource, @Nullable ValueFormatter formatter, + AggregationContext context, Aggregator parent, Map metaData) { super(name, estimatedBucketsCount, context, parent, metaData); this.valuesSource = valuesSource; + this.formatter = formatter; if (valuesSource != null) { final long initialSize = estimatedBucketsCount < 2 ? 1 : estimatedBucketsCount; sums = bigArrays.newDoubleArray(initialSize, true); @@ -82,14 +87,14 @@ public class SumAggregator extends NumericMetricsAggregator.SingleValue { @Override public InternalAggregation buildAggregation(long owningBucketOrdinal) { if (valuesSource == null) { - return new InternalSum(name, 0, getMetaData()); + return new InternalSum(name, 0, formatter, getMetaData()); } - return new InternalSum(name, sums.get(owningBucketOrdinal), getMetaData()); + return new InternalSum(name, sums.get(owningBucketOrdinal), formatter, getMetaData()); } @Override public InternalAggregation buildEmptyAggregation() { - return new InternalSum(name, 0.0, getMetaData()); + return new InternalSum(name, 0.0, formatter, getMetaData()); } public static class Factory extends ValuesSourceAggregatorFactory.LeafOnly> { @@ -100,12 +105,12 @@ public class SumAggregator extends NumericMetricsAggregator.SingleValue { @Override protected Aggregator createUnmapped(AggregationContext aggregationContext, Aggregator parent, Map metaData) { - return new SumAggregator(name, 0, null, aggregationContext, parent, metaData); + return new SumAggregator(name, 0, null, config.formatter(), aggregationContext, parent, metaData); } @Override protected Aggregator create(ValuesSource.Numeric valuesSource, long expectedBucketsCount, AggregationContext aggregationContext, Aggregator parent, Map metaData) { - return new SumAggregator(name, expectedBucketsCount, valuesSource, aggregationContext, parent, metaData); + return new SumAggregator(name, expectedBucketsCount, valuesSource, config.formatter(), aggregationContext, parent, metaData); } } diff --git a/src/main/java/org/elasticsearch/search/aggregations/metrics/valuecount/InternalValueCount.java b/src/main/java/org/elasticsearch/search/aggregations/metrics/valuecount/InternalValueCount.java index f5a6739d322..062e88fce5f 100644 --- a/src/main/java/org/elasticsearch/search/aggregations/metrics/valuecount/InternalValueCount.java +++ b/src/main/java/org/elasticsearch/search/aggregations/metrics/valuecount/InternalValueCount.java @@ -18,12 +18,14 @@ */ package org.elasticsearch.search.aggregations.metrics.valuecount; +import org.elasticsearch.common.inject.internal.Nullable; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.search.aggregations.AggregationStreams; import org.elasticsearch.search.aggregations.InternalAggregation; import org.elasticsearch.search.aggregations.metrics.InternalNumericMetricsAggregation; +import org.elasticsearch.search.aggregations.support.format.ValueFormatter; import java.io.IOException; import java.util.Map; @@ -52,9 +54,10 @@ public class InternalValueCount extends InternalNumericMetricsAggregation.Single InternalValueCount() {} // for serialization - public InternalValueCount(String name, long value, Map metaData) { + public InternalValueCount(String name, long value, @Nullable ValueFormatter formatter, Map metaData) { super(name, metaData); this.value = value; + this.valueFormatter = formatter; } @Override @@ -78,7 +81,7 @@ public class InternalValueCount extends InternalNumericMetricsAggregation.Single for (InternalAggregation aggregation : reduceContext.aggregations()) { valueCount += ((InternalValueCount) aggregation).value; } - return new InternalValueCount(name, valueCount, getMetaData()); + return new InternalValueCount(name, valueCount, valueFormatter, getMetaData()); } @Override @@ -93,7 +96,11 @@ public class InternalValueCount extends InternalNumericMetricsAggregation.Single @Override public XContentBuilder doXContentBody(XContentBuilder builder, Params params) throws IOException { - return builder.field(CommonFields.VALUE, value); + builder.field(CommonFields.VALUE, value); + if (valueFormatter != null) { + builder.field(CommonFields.VALUE_AS_STRING, valueFormatter.format(value)); + } + return builder; } @Override diff --git a/src/main/java/org/elasticsearch/search/aggregations/metrics/valuecount/ValueCount.java b/src/main/java/org/elasticsearch/search/aggregations/metrics/valuecount/ValueCount.java index 1863c7bd4b0..a66d9827498 100644 --- a/src/main/java/org/elasticsearch/search/aggregations/metrics/valuecount/ValueCount.java +++ b/src/main/java/org/elasticsearch/search/aggregations/metrics/valuecount/ValueCount.java @@ -18,13 +18,13 @@ */ package org.elasticsearch.search.aggregations.metrics.valuecount; -import org.elasticsearch.search.aggregations.Aggregation; +import org.elasticsearch.search.aggregations.metrics.NumericMetricsAggregation; /** * An get that holds the number of values that the current document set has for a specific * field. */ -public interface ValueCount extends Aggregation { +public interface ValueCount extends NumericMetricsAggregation.SingleValue { /** * @return The count diff --git a/src/main/java/org/elasticsearch/search/aggregations/metrics/valuecount/ValueCountAggregator.java b/src/main/java/org/elasticsearch/search/aggregations/metrics/valuecount/ValueCountAggregator.java index 04956871232..10febb775b4 100644 --- a/src/main/java/org/elasticsearch/search/aggregations/metrics/valuecount/ValueCountAggregator.java +++ b/src/main/java/org/elasticsearch/search/aggregations/metrics/valuecount/ValueCountAggregator.java @@ -19,6 +19,7 @@ package org.elasticsearch.search.aggregations.metrics.valuecount; import org.apache.lucene.index.LeafReaderContext; +import org.elasticsearch.common.inject.internal.Nullable; import org.elasticsearch.common.lease.Releasables; import org.elasticsearch.common.util.LongArray; import org.elasticsearch.index.fielddata.SortedBinaryDocValues; @@ -29,6 +30,7 @@ import org.elasticsearch.search.aggregations.support.AggregationContext; import org.elasticsearch.search.aggregations.support.ValuesSource; import org.elasticsearch.search.aggregations.support.ValuesSourceAggregatorFactory; import org.elasticsearch.search.aggregations.support.ValuesSourceConfig; +import org.elasticsearch.search.aggregations.support.format.ValueFormatter; import java.io.IOException; import java.util.Map; @@ -46,10 +48,13 @@ public class ValueCountAggregator extends NumericMetricsAggregator.SingleValue { // a count per bucket LongArray counts; + private ValueFormatter formatter; - public ValueCountAggregator(String name, long expectedBucketsCount, ValuesSource valuesSource, AggregationContext aggregationContext, Aggregator parent, Map metaData) { + public ValueCountAggregator(String name, long expectedBucketsCount, ValuesSource valuesSource, @Nullable ValueFormatter formatter, + AggregationContext aggregationContext, Aggregator parent, Map metaData) { super(name, 0, aggregationContext, parent, metaData); this.valuesSource = valuesSource; + this.formatter = formatter; if (valuesSource != null) { // expectedBucketsCount == 0 means it's a top level bucket final long initialSize = expectedBucketsCount < 2 ? 1 : expectedBucketsCount; @@ -82,15 +87,15 @@ public class ValueCountAggregator extends NumericMetricsAggregator.SingleValue { @Override public InternalAggregation buildAggregation(long owningBucketOrdinal) { if (valuesSource == null) { - return new InternalValueCount(name, 0, getMetaData()); + return new InternalValueCount(name, 0, formatter, getMetaData()); } assert owningBucketOrdinal < counts.size(); - return new InternalValueCount(name, counts.get(owningBucketOrdinal), getMetaData()); + return new InternalValueCount(name, counts.get(owningBucketOrdinal), formatter, getMetaData()); } @Override public InternalAggregation buildEmptyAggregation() { - return new InternalValueCount(name, 0l, getMetaData()); + return new InternalValueCount(name, 0l, formatter, getMetaData()); } @Override @@ -106,12 +111,13 @@ public class ValueCountAggregator extends NumericMetricsAggregator.SingleValue { @Override protected Aggregator createUnmapped(AggregationContext aggregationContext, Aggregator parent, Map metaData) { - return new ValueCountAggregator(name, 0, null, aggregationContext, parent, metaData); + return new ValueCountAggregator(name, 0, null, config.formatter(), aggregationContext, parent, metaData); } @Override protected Aggregator create(VS valuesSource, long expectedBucketsCount, AggregationContext aggregationContext, Aggregator parent, Map metaData) { - return new ValueCountAggregator(name, expectedBucketsCount, valuesSource, aggregationContext, parent, metaData); + return new ValueCountAggregator(name, expectedBucketsCount, valuesSource, config.formatter(), aggregationContext, parent, + metaData); } } diff --git a/src/test/java/org/elasticsearch/search/aggregations/metrics/AvgTests.java b/src/test/java/org/elasticsearch/search/aggregations/metrics/AvgTests.java index 420cdcba198..ce0e7e0c1f8 100644 --- a/src/test/java/org/elasticsearch/search/aggregations/metrics/AvgTests.java +++ b/src/test/java/org/elasticsearch/search/aggregations/metrics/AvgTests.java @@ -22,7 +22,6 @@ import org.elasticsearch.action.search.SearchResponse; import org.elasticsearch.search.aggregations.bucket.global.Global; import org.elasticsearch.search.aggregations.bucket.histogram.Histogram; import org.elasticsearch.search.aggregations.metrics.avg.Avg; -import org.elasticsearch.test.junit.annotations.TestLogging; import org.junit.Test; import static org.elasticsearch.index.query.QueryBuilders.matchAllQuery; @@ -158,6 +157,18 @@ public class AvgTests extends AbstractNumericTests { assertThat(avg.getValue(), equalTo((double) (2+3+4+5+6+7+8+9+10+11) / 10)); } + public void testSingleValuedField_WithFormatter() throws Exception { + SearchResponse searchResponse = client().prepareSearch("idx").setQuery(matchAllQuery()) + .addAggregation(avg("avg").format("#").field("value")).execute().actionGet(); + + assertThat(searchResponse.getHits().getTotalHits(), equalTo(10l)); + + Avg avg = searchResponse.getAggregations().get("avg"); + assertThat(avg, notNullValue()); + assertThat(avg.getName(), equalTo("avg")); + assertThat(avg.getValue(), equalTo((double) (1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10) / 10)); + assertThat(avg.getValueAsString(), equalTo("6")); + } @Test public void testMultiValuedField() throws Exception { diff --git a/src/test/java/org/elasticsearch/search/aggregations/metrics/ExtendedStatsTests.java b/src/test/java/org/elasticsearch/search/aggregations/metrics/ExtendedStatsTests.java index d3d295e56ae..79d624b1e0e 100644 --- a/src/test/java/org/elasticsearch/search/aggregations/metrics/ExtendedStatsTests.java +++ b/src/test/java/org/elasticsearch/search/aggregations/metrics/ExtendedStatsTests.java @@ -123,6 +123,33 @@ public class ExtendedStatsTests extends AbstractNumericTests { assertThat(stats.getStdDeviation(), equalTo(stdDev(1, 2, 3, 4, 5, 6, 7, 8 ,9, 10))); } + public void testSingleValuedField_WithFormatter() throws Exception { + SearchResponse searchResponse = client().prepareSearch("idx").setQuery(matchAllQuery()) + .addAggregation(extendedStats("stats").format("0000.0").field("value")).execute().actionGet(); + + assertThat(searchResponse.getHits().getTotalHits(), equalTo(10l)); + + ExtendedStats stats = searchResponse.getAggregations().get("stats"); + assertThat(stats, notNullValue()); + assertThat(stats.getName(), equalTo("stats")); + assertThat(stats.getAvg(), equalTo((double) (1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10) / 10)); + assertThat(stats.getAvgAsString(), equalTo("0005.5")); + assertThat(stats.getMin(), equalTo(1.0)); + assertThat(stats.getMinAsString(), equalTo("0001.0")); + assertThat(stats.getMax(), equalTo(10.0)); + assertThat(stats.getMaxAsString(), equalTo("0010.0")); + assertThat(stats.getSum(), equalTo((double) 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10)); + assertThat(stats.getSumAsString(), equalTo("0055.0")); + assertThat(stats.getCount(), equalTo(10l)); + assertThat(stats.getCountAsString(), equalTo("0010.0")); + assertThat(stats.getSumOfSquares(), equalTo((double) 1 + 4 + 9 + 16 + 25 + 36 + 49 + 64 + 81 + 100)); + assertThat(stats.getSumOfSquaresAsString(), equalTo("0385.0")); + assertThat(stats.getVariance(), equalTo(variance(1, 2, 3, 4, 5, 6, 7, 8, 9, 10))); + assertThat(stats.getVarianceAsString(), equalTo("0008.2")); + assertThat(stats.getStdDeviation(), equalTo(stdDev(1, 2, 3, 4, 5, 6, 7, 8, 9, 10))); + assertThat(stats.getStdDeviationAsString(), equalTo("0002.9")); + } + @Test public void testSingleValuedField_getProperty() throws Exception { diff --git a/src/test/java/org/elasticsearch/search/aggregations/metrics/MaxTests.java b/src/test/java/org/elasticsearch/search/aggregations/metrics/MaxTests.java index f874c008c1d..32a335eef8c 100644 --- a/src/test/java/org/elasticsearch/search/aggregations/metrics/MaxTests.java +++ b/src/test/java/org/elasticsearch/search/aggregations/metrics/MaxTests.java @@ -86,6 +86,20 @@ public class MaxTests extends AbstractNumericTests { assertThat(max.getValue(), equalTo(10.0)); } + @Test + public void testSingleValuedField_WithFormatter() throws Exception { + SearchResponse searchResponse = client().prepareSearch("idx").setQuery(matchAllQuery()) + .addAggregation(max("max").format("0000.0").field("value")).execute().actionGet(); + + assertThat(searchResponse.getHits().getTotalHits(), equalTo(10l)); + + Max max = searchResponse.getAggregations().get("max"); + assertThat(max, notNullValue()); + assertThat(max.getName(), equalTo("max")); + assertThat(max.getValue(), equalTo(10.0)); + assertThat(max.getValueAsString(), equalTo("0010.0")); + } + @Test public void testSingleValuedField_getProperty() throws Exception { diff --git a/src/test/java/org/elasticsearch/search/aggregations/metrics/MinTests.java b/src/test/java/org/elasticsearch/search/aggregations/metrics/MinTests.java index 956cf53c1a7..b9d916aad25 100644 --- a/src/test/java/org/elasticsearch/search/aggregations/metrics/MinTests.java +++ b/src/test/java/org/elasticsearch/search/aggregations/metrics/MinTests.java @@ -86,6 +86,20 @@ public class MinTests extends AbstractNumericTests { assertThat(min.getValue(), equalTo(1.0)); } + @Test + public void testSingleValuedField_WithFormatter() throws Exception { + SearchResponse searchResponse = client().prepareSearch("idx").setQuery(matchAllQuery()) + .addAggregation(min("min").format("0000.0").field("value")).execute().actionGet(); + + assertThat(searchResponse.getHits().getTotalHits(), equalTo(10l)); + + Min min = searchResponse.getAggregations().get("min"); + assertThat(min, notNullValue()); + assertThat(min.getName(), equalTo("min")); + assertThat(min.getValue(), equalTo(1.0)); + assertThat(min.getValueAsString(), equalTo("0001.0")); + } + @Test public void testSingleValuedField_getProperty() throws Exception { diff --git a/src/test/java/org/elasticsearch/search/aggregations/metrics/PercentilesTests.java b/src/test/java/org/elasticsearch/search/aggregations/metrics/PercentilesTests.java index 721947bae03..f233171ec00 100644 --- a/src/test/java/org/elasticsearch/search/aggregations/metrics/PercentilesTests.java +++ b/src/test/java/org/elasticsearch/search/aggregations/metrics/PercentilesTests.java @@ -19,6 +19,7 @@ package org.elasticsearch.search.aggregations.metrics; import com.google.common.collect.Lists; + import org.elasticsearch.action.search.SearchResponse; import org.elasticsearch.common.logging.Loggers; import org.elasticsearch.search.aggregations.bucket.global.Global; diff --git a/src/test/java/org/elasticsearch/search/aggregations/metrics/StatsTests.java b/src/test/java/org/elasticsearch/search/aggregations/metrics/StatsTests.java index 908739618a0..3510f218797 100644 --- a/src/test/java/org/elasticsearch/search/aggregations/metrics/StatsTests.java +++ b/src/test/java/org/elasticsearch/search/aggregations/metrics/StatsTests.java @@ -23,7 +23,6 @@ import org.elasticsearch.action.search.ShardSearchFailure; import org.elasticsearch.search.aggregations.bucket.global.Global; import org.elasticsearch.search.aggregations.bucket.histogram.Histogram; import org.elasticsearch.search.aggregations.metrics.stats.Stats; -import org.elasticsearch.test.junit.annotations.TestLogging; import org.junit.Test; import static org.elasticsearch.index.query.QueryBuilders.matchAllQuery; @@ -108,6 +107,28 @@ public class StatsTests extends AbstractNumericTests { assertThat(stats.getCount(), equalTo(10l)); } + public void testSingleValuedField_WithFormatter() throws Exception { + + SearchResponse searchResponse = client().prepareSearch("idx").setQuery(matchAllQuery()) + .addAggregation(stats("stats").format("0000.0").field("value")).execute().actionGet(); + + assertThat(searchResponse.getHits().getTotalHits(), equalTo(10l)); + + Stats stats = searchResponse.getAggregations().get("stats"); + assertThat(stats, notNullValue()); + assertThat(stats.getName(), equalTo("stats")); + assertThat(stats.getAvg(), equalTo((double) (1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10) / 10)); + assertThat(stats.getAvgAsString(), equalTo("0005.5")); + assertThat(stats.getMin(), equalTo(1.0)); + assertThat(stats.getMinAsString(), equalTo("0001.0")); + assertThat(stats.getMax(), equalTo(10.0)); + assertThat(stats.getMaxAsString(), equalTo("0010.0")); + assertThat(stats.getSum(), equalTo((double) 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10)); + assertThat(stats.getSumAsString(), equalTo("0055.0")); + assertThat(stats.getCount(), equalTo(10l)); + assertThat(stats.getCountAsString(), equalTo("0010.0")); + } + @Test public void testSingleValuedField_getProperty() throws Exception { diff --git a/src/test/java/org/elasticsearch/search/aggregations/metrics/SumTests.java b/src/test/java/org/elasticsearch/search/aggregations/metrics/SumTests.java index 6cb6e8cfd82..4340c3e2ddc 100644 --- a/src/test/java/org/elasticsearch/search/aggregations/metrics/SumTests.java +++ b/src/test/java/org/elasticsearch/search/aggregations/metrics/SumTests.java @@ -86,6 +86,20 @@ public class SumTests extends AbstractNumericTests { assertThat(sum.getValue(), equalTo((double) 1+2+3+4+5+6+7+8+9+10)); } + @Test + public void testSingleValuedField_WithFormatter() throws Exception { + SearchResponse searchResponse = client().prepareSearch("idx").setQuery(matchAllQuery()) + .addAggregation(sum("sum").format("0000.0").field("value")).execute().actionGet(); + + assertThat(searchResponse.getHits().getTotalHits(), equalTo(10l)); + + Sum sum = searchResponse.getAggregations().get("sum"); + assertThat(sum, notNullValue()); + assertThat(sum.getName(), equalTo("sum")); + assertThat(sum.getValue(), equalTo((double) 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10)); + assertThat(sum.getValueAsString(), equalTo("0055.0")); + } + @Test public void testSingleValuedField_getProperty() throws Exception {