|
@@ -22,6 +22,7 @@ import org.elasticsearch.common.util.FeatureFlag;
|
|
|
import org.elasticsearch.exponentialhistogram.ExponentialHistogram;
|
|
|
import org.elasticsearch.exponentialhistogram.ExponentialHistogramUtils;
|
|
|
import org.elasticsearch.exponentialhistogram.ExponentialHistogramXContent;
|
|
|
+import org.elasticsearch.exponentialhistogram.ZeroBucket;
|
|
|
import org.elasticsearch.index.fielddata.FieldDataContext;
|
|
|
import org.elasticsearch.index.fielddata.IndexFieldData;
|
|
|
import org.elasticsearch.index.mapper.CompositeSyntheticFieldLoader;
|
|
@@ -48,6 +49,7 @@ import java.util.Collections;
|
|
|
import java.util.Comparator;
|
|
|
import java.util.List;
|
|
|
import java.util.Map;
|
|
|
+import java.util.OptionalDouble;
|
|
|
|
|
|
import static org.elasticsearch.common.xcontent.XContentParserUtils.ensureExpectedToken;
|
|
|
import static org.elasticsearch.exponentialhistogram.ExponentialHistogram.MAX_INDEX;
|
|
@@ -72,6 +74,8 @@ import static org.elasticsearch.exponentialhistogram.ExponentialHistogram.MIN_IN
|
|
|
* <pre><code>{
|
|
|
* "my_histo": {
|
|
|
* "scale": 12,
|
|
|
+ * "sum": 1234,
|
|
|
+ * "min": -123.456,
|
|
|
* "zero": {
|
|
|
* "threshold": 0.123456,
|
|
|
* "count": 42
|
|
@@ -95,6 +99,7 @@ public class ExponentialHistogramFieldMapper extends FieldMapper {
|
|
|
|
|
|
public static final ParseField SCALE_FIELD = new ParseField(ExponentialHistogramXContent.SCALE_FIELD);
|
|
|
public static final ParseField SUM_FIELD = new ParseField(ExponentialHistogramXContent.SUM_FIELD);
|
|
|
+ public static final ParseField MIN_FIELD = new ParseField(ExponentialHistogramXContent.MIN_FIELD);
|
|
|
public static final ParseField ZERO_FIELD = new ParseField(ExponentialHistogramXContent.ZERO_FIELD);
|
|
|
public static final ParseField ZERO_COUNT_FIELD = new ParseField(ExponentialHistogramXContent.ZERO_COUNT_FIELD);
|
|
|
public static final ParseField ZERO_THRESHOLD_FIELD = new ParseField(ExponentialHistogramXContent.ZERO_THRESHOLD_FIELD);
|
|
@@ -140,6 +145,10 @@ public class ExponentialHistogramFieldMapper extends FieldMapper {
|
|
|
return fullPath + "._values_sum";
|
|
|
}
|
|
|
|
|
|
+ private static String valuesMinSubFieldName(String fullPath) {
|
|
|
+ return fullPath + "._values_min";
|
|
|
+ }
|
|
|
+
|
|
|
static class Builder extends FieldMapper.Builder {
|
|
|
|
|
|
private final FieldMapper.Parameter<Map<String, String>> meta = FieldMapper.Parameter.metaParam();
|
|
@@ -266,6 +275,7 @@ public class ExponentialHistogramFieldMapper extends FieldMapper {
|
|
|
}
|
|
|
|
|
|
Double sum = null;
|
|
|
+ Double min = null;
|
|
|
Integer scale = null;
|
|
|
ParsedZeroBucket zeroBucket = ParsedZeroBucket.DEFAULT;
|
|
|
List<IndexWithCount> negativeBuckets = Collections.emptyList();
|
|
@@ -305,6 +315,8 @@ public class ExponentialHistogramFieldMapper extends FieldMapper {
|
|
|
}
|
|
|
} else if (fieldName.equals(SUM_FIELD.getPreferredName())) {
|
|
|
sum = parseDoubleAllowingInfinity(subParser);
|
|
|
+ } else if (fieldName.equals(MIN_FIELD.getPreferredName())) {
|
|
|
+ min = parseDoubleAllowingInfinity(subParser);
|
|
|
} else if (fieldName.equals(ZERO_FIELD.getPreferredName())) {
|
|
|
zeroBucket = parseZeroBucket(subParser);
|
|
|
} else if (fieldName.equals(POSITIVE_FIELD.getPreferredName())) {
|
|
@@ -347,8 +359,8 @@ public class ExponentialHistogramFieldMapper extends FieldMapper {
|
|
|
|
|
|
if (sum == null) {
|
|
|
sum = ExponentialHistogramUtils.estimateSum(
|
|
|
- IndexWithCount.asBucketIterator(scale, negativeBuckets),
|
|
|
- IndexWithCount.asBucketIterator(scale, positiveBuckets)
|
|
|
+ IndexWithCount.asBuckets(scale, negativeBuckets).iterator(),
|
|
|
+ IndexWithCount.asBuckets(scale, positiveBuckets).iterator()
|
|
|
);
|
|
|
} else {
|
|
|
if (totalValueCount == 0 && sum != 0.0) {
|
|
@@ -359,6 +371,22 @@ public class ExponentialHistogramFieldMapper extends FieldMapper {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ if (min == null) {
|
|
|
+ OptionalDouble estimatedMin = ExponentialHistogramUtils.estimateMin(
|
|
|
+ new ZeroBucket(zeroBucket.threshold(), zeroBucket.count),
|
|
|
+ IndexWithCount.asBuckets(scale, negativeBuckets),
|
|
|
+ IndexWithCount.asBuckets(scale, positiveBuckets)
|
|
|
+ );
|
|
|
+ if (estimatedMin.isPresent()) {
|
|
|
+ min = estimatedMin.getAsDouble();
|
|
|
+ }
|
|
|
+ } else if (totalValueCount == 0) {
|
|
|
+ throw new DocumentParsingException(
|
|
|
+ subParser.getTokenLocation(),
|
|
|
+ "error parsing field [" + fullPath() + "], min field must be null if the histogram is empty, but got " + min
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
BytesStreamOutput histogramBytesOutput = new BytesStreamOutput();
|
|
|
CompressedExponentialHistogram.writeHistogramBytes(histogramBytesOutput, scale, negativeBuckets, positiveBuckets);
|
|
|
BytesRef histoBytes = histogramBytesOutput.bytes().toBytesRef();
|
|
@@ -376,6 +404,13 @@ public class ExponentialHistogramFieldMapper extends FieldMapper {
|
|
|
context.doc().add(zeroThresholdField);
|
|
|
context.doc().add(valuesCountField);
|
|
|
context.doc().add(sumField);
|
|
|
+ if (min != null) {
|
|
|
+ NumericDocValuesField minField = new NumericDocValuesField(
|
|
|
+ valuesMinSubFieldName(fullPath()),
|
|
|
+ NumericUtils.doubleToSortableLong(min)
|
|
|
+ );
|
|
|
+ context.doc().add(minField);
|
|
|
+ }
|
|
|
|
|
|
} catch (Exception ex) {
|
|
|
if (ignoreMalformed.value() == false) {
|
|
@@ -629,6 +664,7 @@ public class ExponentialHistogramFieldMapper extends FieldMapper {
|
|
|
private double zeroThreshold;
|
|
|
private long valueCount;
|
|
|
private double valueSum;
|
|
|
+ private double valueMin;
|
|
|
|
|
|
@Override
|
|
|
public SourceLoader.SyntheticFieldLoader.DocValuesLoader docValuesLoader(LeafReader leafReader, int[] docIdsInLeaf)
|
|
@@ -642,6 +678,7 @@ public class ExponentialHistogramFieldMapper extends FieldMapper {
|
|
|
NumericDocValues zeroThresholds = leafReader.getNumericDocValues(zeroThresholdSubFieldName(fullPath()));
|
|
|
NumericDocValues valueCounts = leafReader.getNumericDocValues(valuesCountSubFieldName(fullPath()));
|
|
|
NumericDocValues valueSums = leafReader.getNumericDocValues(valuesSumSubFieldName(fullPath()));
|
|
|
+ NumericDocValues valueMins = leafReader.getNumericDocValues(valuesMinSubFieldName(fullPath()));
|
|
|
assert zeroThresholds != null;
|
|
|
assert valueCounts != null;
|
|
|
assert valueSums != null;
|
|
@@ -657,6 +694,12 @@ public class ExponentialHistogramFieldMapper extends FieldMapper {
|
|
|
zeroThreshold = NumericUtils.sortableLongToDouble(zeroThresholds.longValue());
|
|
|
valueCount = valueCounts.longValue();
|
|
|
valueSum = NumericUtils.sortableLongToDouble(valueSums.longValue());
|
|
|
+
|
|
|
+ if (valueMins != null && valueMins.advanceExact(docId)) {
|
|
|
+ valueMin = NumericUtils.sortableLongToDouble(valueMins.longValue());
|
|
|
+ } else {
|
|
|
+ valueMin = Double.NaN;
|
|
|
+ }
|
|
|
return true;
|
|
|
}
|
|
|
binaryValue = null;
|
|
@@ -675,7 +718,7 @@ public class ExponentialHistogramFieldMapper extends FieldMapper {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- histogram.reset(zeroThreshold, valueCount, valueSum, binaryValue);
|
|
|
+ histogram.reset(zeroThreshold, valueCount, valueSum, valueMin, binaryValue);
|
|
|
ExponentialHistogramXContent.serialize(b, histogram);
|
|
|
}
|
|
|
|