Add parsing for InternalSimpleValue and InternalDerivative (#24162)

This commit is contained in:
Christoph Büscher 2017-04-19 12:58:26 +02:00 committed by GitHub
parent bf5cfabe04
commit 4562c8a345
10 changed files with 183 additions and 14 deletions

View File

@ -63,7 +63,7 @@ public abstract class ParsedSingleValueNumericMetricsAggregation extends ParsedA
}
}
protected static void declareSingeValueFields(ObjectParser<? extends ParsedSingleValueNumericMetricsAggregation, Void> objectParser,
protected static void declareSingleValueFields(ObjectParser<? extends ParsedSingleValueNumericMetricsAggregation, Void> objectParser,
double defaultNullValue) {
declareAggregationFields(objectParser);
objectParser.declareField(ParsedSingleValueNumericMetricsAggregation::setValue,

View File

@ -53,7 +53,7 @@ public class ParsedAvg extends ParsedSingleValueNumericMetricsAggregation implem
private static final ObjectParser<ParsedAvg, Void> PARSER = new ObjectParser<>(ParsedAvg.class.getSimpleName(), true, ParsedAvg::new);
static {
declareSingeValueFields(PARSER, Double.POSITIVE_INFINITY);
declareSingleValueFields(PARSER, Double.POSITIVE_INFINITY);
}
public static ParsedAvg fromXContent(XContentParser parser, final String name) {

View File

@ -51,7 +51,7 @@ public class ParsedMax extends ParsedSingleValueNumericMetricsAggregation implem
private static final ObjectParser<ParsedMax, Void> PARSER = new ObjectParser<>(ParsedMax.class.getSimpleName(), true, ParsedMax::new);
static {
declareSingeValueFields(PARSER, Double.NEGATIVE_INFINITY);
declareSingleValueFields(PARSER, Double.NEGATIVE_INFINITY);
}
public static ParsedMax fromXContent(XContentParser parser, final String name) {

View File

@ -51,7 +51,7 @@ public class ParsedMin extends ParsedSingleValueNumericMetricsAggregation implem
private static final ObjectParser<ParsedMin, Void> PARSER = new ObjectParser<>(ParsedMin.class.getSimpleName(), true, ParsedMin::new);
static {
declareSingeValueFields(PARSER, Double.POSITIVE_INFINITY);
declareSingleValueFields(PARSER, Double.POSITIVE_INFINITY);
}
public static ParsedMin fromXContent(XContentParser parser, final String name) {

View File

@ -50,7 +50,7 @@ public class ParsedSum extends ParsedSingleValueNumericMetricsAggregation implem
private static final ObjectParser<ParsedSum, Void> PARSER = new ObjectParser<>(ParsedSum.class.getSimpleName(), true, ParsedSum::new);
static {
declareSingeValueFields(PARSER, Double.NEGATIVE_INFINITY);
declareSingleValueFields(PARSER, Double.NEGATIVE_INFINITY);
}
public static ParsedSum fromXContent(XContentParser parser, final String name) {

View File

@ -0,0 +1,58 @@
/*
* 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.pipeline;
import org.elasticsearch.common.xcontent.ObjectParser;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.search.aggregations.metrics.ParsedSingleValueNumericMetricsAggregation;
import java.io.IOException;
public class ParsedSimpleValue extends ParsedSingleValueNumericMetricsAggregation implements SimpleValue {
@Override
protected String getType() {
return InternalSimpleValue.NAME;
}
private static final ObjectParser<ParsedSimpleValue, Void> PARSER = new ObjectParser<>(ParsedSimpleValue.class.getSimpleName(), true,
ParsedSimpleValue::new);
static {
declareSingleValueFields(PARSER, Double.NaN);
}
public static ParsedSimpleValue fromXContent(XContentParser parser, final String name) {
ParsedSimpleValue simpleValue = PARSER.apply(parser, null);
simpleValue.setName(name);
return simpleValue;
}
@Override
protected XContentBuilder doXContentBody(XContentBuilder builder, Params params) throws IOException {
boolean hasValue = Double.isNaN(value) == false;
builder.field(CommonFields.VALUE.getPreferredName(), hasValue ? value : null);
if (hasValue && valueAsString != null) {
builder.field(CommonFields.VALUE_AS_STRING.getPreferredName(), valueAsString);
}
return builder;
}
}

View File

@ -0,0 +1,79 @@
/*
* 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.pipeline.derivative;
import org.elasticsearch.common.ParseField;
import org.elasticsearch.common.xcontent.ObjectParser;
import org.elasticsearch.common.xcontent.ObjectParser.ValueType;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.search.aggregations.pipeline.ParsedSimpleValue;
import java.io.IOException;
public class ParsedDerivative extends ParsedSimpleValue implements Derivative {
private double normalizedValue;
private String normalizedAsString;
private boolean hasNormalizationFactor;
private static final ParseField NORMALIZED_AS_STRING = new ParseField("normalized_value_as_string");
private static final ParseField NORMALIZED = new ParseField("normalized_value");
@Override
public double normalizedValue() {
return this.normalizedValue;
}
@Override
protected String getType() {
return DerivativePipelineAggregationBuilder.NAME;
}
private static final ObjectParser<ParsedDerivative, Void> PARSER = new ObjectParser<>(ParsedDerivative.class.getSimpleName(), true,
ParsedDerivative::new);
static {
declareSingleValueFields(PARSER, Double.NaN);
PARSER.declareField((agg, normalized) -> {
agg.normalizedValue = normalized;
agg.hasNormalizationFactor = true;
}, (parser, context) -> parseValue(parser, Double.NaN), NORMALIZED, ValueType.DOUBLE_OR_NULL);
PARSER.declareString((agg, normalAsString) -> agg.normalizedAsString = normalAsString, NORMALIZED_AS_STRING);
}
public static ParsedDerivative fromXContent(XContentParser parser, final String name) {
ParsedDerivative derivative = PARSER.apply(parser, null);
derivative.setName(name);
return derivative;
}
@Override
protected XContentBuilder doXContentBody(XContentBuilder builder, Params params) throws IOException {
super.doXContentBody(builder, params);
if (hasNormalizationFactor) {
boolean hasValue = Double.isNaN(normalizedValue) == false;
builder.field(NORMALIZED.getPreferredName(), hasValue ? normalizedValue : null);
if (hasValue && normalizedAsString != null) {
builder.field(NORMALIZED_AS_STRING.getPreferredName(), normalizedAsString);
}
}
return builder;
}
}

View File

@ -51,7 +51,11 @@ import org.elasticsearch.search.aggregations.metrics.sum.ParsedSum;
import org.elasticsearch.search.aggregations.metrics.sum.SumAggregationBuilder;
import org.elasticsearch.search.aggregations.metrics.valuecount.ParsedValueCount;
import org.elasticsearch.search.aggregations.metrics.valuecount.ValueCountAggregationBuilder;
import org.elasticsearch.search.aggregations.pipeline.InternalSimpleValue;
import org.elasticsearch.search.aggregations.pipeline.ParsedSimpleValue;
import org.elasticsearch.search.aggregations.pipeline.PipelineAggregator;
import org.elasticsearch.search.aggregations.pipeline.derivative.DerivativePipelineAggregationBuilder;
import org.elasticsearch.search.aggregations.pipeline.derivative.ParsedDerivative;
import org.elasticsearch.test.AbstractWireSerializingTestCase;
import java.io.IOException;
@ -85,6 +89,8 @@ public abstract class InternalAggregationTestCase<T extends InternalAggregation>
namedXContents.put(SumAggregationBuilder.NAME, (p, c) -> ParsedSum.fromXContent(p, (String) c));
namedXContents.put(AvgAggregationBuilder.NAME, (p, c) -> ParsedAvg.fromXContent(p, (String) c));
namedXContents.put(ValueCountAggregationBuilder.NAME, (p, c) -> ParsedValueCount.fromXContent(p, (String) c));
namedXContents.put(InternalSimpleValue.NAME, (p, c) -> ParsedSimpleValue.fromXContent(p, (String) c));
namedXContents.put(DerivativePipelineAggregationBuilder.NAME, (p, c) -> ParsedDerivative.fromXContent(p, (String) c));
return namedXContents.entrySet().stream()
.map(entry -> new NamedXContentRegistry.Entry(Aggregation.class, new ParseField(entry.getKey()), entry.getValue()))

View File

@ -22,6 +22,7 @@ package org.elasticsearch.search.aggregations.pipeline;
import org.elasticsearch.common.io.stream.Writeable.Reader;
import org.elasticsearch.search.DocValueFormat;
import org.elasticsearch.search.aggregations.InternalAggregationTestCase;
import org.elasticsearch.search.aggregations.ParsedAggregation;
import java.util.Collections;
import java.util.List;
@ -30,18 +31,18 @@ import java.util.Map;
public class InternalSimpleValueTests extends InternalAggregationTestCase<InternalSimpleValue>{
@Override
protected InternalSimpleValue createTestInstance(String name,
List<PipelineAggregator> pipelineAggregators, Map<String, Object> metaData) {
protected InternalSimpleValue createTestInstance(String name, List<PipelineAggregator> pipelineAggregators,
Map<String, Object> metaData) {
DocValueFormat formatter = randomNumericDocValueFormat();
double value = randomDoubleBetween(0, 100000, true);
double value = frequently() ? randomDoubleBetween(0, 100000, true)
: randomFrom(new Double[] { Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, Double.NaN });
return new InternalSimpleValue(name, value, formatter, pipelineAggregators, metaData);
}
@Override
public void testReduceRandom() {
expectThrows(UnsupportedOperationException.class,
() -> createTestInstance("name", Collections.emptyList(), null).reduce(null,
null));
() -> createTestInstance("name", Collections.emptyList(), null).reduce(null, null));
}
@Override
@ -54,4 +55,16 @@ public class InternalSimpleValueTests extends InternalAggregationTestCase<Intern
return InternalSimpleValue::new;
}
@Override
protected void assertFromXContent(InternalSimpleValue simpleValue, ParsedAggregation parsedAggregation) {
ParsedSimpleValue parsed = ((ParsedSimpleValue) parsedAggregation);
if (Double.isInfinite(simpleValue.getValue()) == false && Double.isNaN(simpleValue.getValue()) == false) {
assertEquals(simpleValue.getValue(), parsed.value(), 0);
assertEquals(simpleValue.getValueAsString(), parsed.getValueAsString());
} else {
// we write Double.NEGATIVE_INFINITY, Double.POSITIVE amd Double.NAN to xContent as 'null', so we
// cannot differentiate between them. Also we cannot recreate the exact String representation
assertEquals(parsed.value(), Double.NaN, 0);
}
}
}

View File

@ -22,6 +22,7 @@ package org.elasticsearch.search.aggregations.pipeline.derivative;
import org.elasticsearch.common.io.stream.Writeable.Reader;
import org.elasticsearch.search.DocValueFormat;
import org.elasticsearch.search.aggregations.InternalAggregationTestCase;
import org.elasticsearch.search.aggregations.ParsedAggregation;
import org.elasticsearch.search.aggregations.pipeline.PipelineAggregator;
import java.util.Collections;
@ -34,16 +35,16 @@ public class InternalDerivativeTests extends InternalAggregationTestCase<Interna
protected InternalDerivative createTestInstance(String name,
List<PipelineAggregator> pipelineAggregators, Map<String, Object> metaData) {
DocValueFormat formatter = randomNumericDocValueFormat();
double value = randomDoubleBetween(0, 100000, true);
double normalizationFactor = randomDoubleBetween(0, 100000, true);
double value = frequently() ? randomDoubleBetween(-100000, 100000, true)
: randomFrom(new Double[] { Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, Double.NaN });
double normalizationFactor = frequently() ? randomDoubleBetween(0, 100000, true) : 0;
return new InternalDerivative(name, value, normalizationFactor, formatter, pipelineAggregators, metaData);
}
@Override
public void testReduceRandom() {
expectThrows(UnsupportedOperationException.class,
() -> createTestInstance("name", Collections.emptyList(), null).reduce(null,
null));
() -> createTestInstance("name", Collections.emptyList(), null).reduce(null, null));
}
@Override
@ -56,4 +57,16 @@ public class InternalDerivativeTests extends InternalAggregationTestCase<Interna
return InternalDerivative::new;
}
@Override
protected void assertFromXContent(InternalDerivative derivative, ParsedAggregation parsedAggregation) {
ParsedDerivative parsed = ((ParsedDerivative) parsedAggregation);
if (Double.isInfinite(derivative.getValue()) == false && Double.isNaN(derivative.getValue()) == false) {
assertEquals(derivative.getValue(), parsed.value(), Double.MIN_VALUE);
assertEquals(derivative.getValueAsString(), parsed.getValueAsString());
} else {
// we write Double.NEGATIVE_INFINITY, Double.POSITIVE amd Double.NAN to xContent as 'null', so we
// cannot differentiate between them. Also we cannot recreate the exact String representation
assertEquals(parsed.value(), Double.NaN, Double.MIN_VALUE);
}
}
}