Adding ParsedCardinality (#23973)

Adding parsing of InternalCardinality xContent output. Parsing method will return a new
implementation of the Cardinality interface, ParsedCardinality.
This commit is contained in:
Christoph Büscher 2017-04-12 11:58:57 +02:00 committed by GitHub
parent f538d7b8d6
commit 356532816a
6 changed files with 144 additions and 7 deletions

View File

@ -38,7 +38,7 @@ public abstract class ParsedAggregation implements Aggregation, ToXContent {
(parser, context) -> parser.map(), InternalAggregation.CommonFields.META); (parser, context) -> parser.map(), InternalAggregation.CommonFields.META);
} }
String name; private String name;
Map<String, Object> metadata; Map<String, Object> metadata;
@Override @Override
@ -46,6 +46,10 @@ public abstract class ParsedAggregation implements Aggregation, ToXContent {
return name; return name;
} }
protected void setName(String name) {
this.name = name;
}
@Override @Override
public final Map<String, Object> getMetaData() { public final Map<String, Object> getMetaData() {
return metadata; return metadata;
@ -59,6 +63,7 @@ public abstract class ParsedAggregation implements Aggregation, ToXContent {
//TODO it may make sense to move getType to the Aggregation interface given that we are duplicating it in both implementations //TODO it may make sense to move getType to the Aggregation interface given that we are duplicating it in both implementations
protected abstract String getType(); protected abstract String getType();
@Override
public XContentBuilder toXContent(XContentBuilder builder, ToXContent.Params params) throws IOException { public XContentBuilder toXContent(XContentBuilder builder, ToXContent.Params params) throws IOException {
// Concatenates the type and the name of the aggregation (ex: top_hits#foo) // Concatenates the type and the name of the aggregation (ex: top_hits#foo)
builder.startObject(String.join(InternalAggregation.TYPED_KEYS_DELIMITER, getType(), name)); builder.startObject(String.join(InternalAggregation.TYPED_KEYS_DELIMITER, getType(), name));
@ -72,4 +77,4 @@ public abstract class ParsedAggregation implements Aggregation, ToXContent {
} }
protected abstract XContentBuilder doXContentBody(XContentBuilder builder, Params params) throws IOException; protected abstract XContentBuilder doXContentBody(XContentBuilder builder, Params params) throws IOException;
} }

View File

@ -128,3 +128,4 @@ public final class InternalCardinality extends InternalNumericMetricsAggregation
return counts; return counts;
} }
} }

View File

@ -0,0 +1,80 @@
/*
* 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.cardinality;
import org.elasticsearch.common.xcontent.ObjectParser;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.search.DocValueFormat;
import org.elasticsearch.search.aggregations.ParsedAggregation;
import java.io.IOException;
public class ParsedCardinality extends ParsedAggregation implements Cardinality {
private long cardinalityValue;
@Override
public String getValueAsString() {
// InternalCardinality doesn't print "value_as_string", but you can get a formated value using
// getValueAsString(). That method uses the raw formatter so we also use it here.
return DocValueFormat.RAW.format((double) cardinalityValue);
}
@Override
public double value() {
return getValue();
}
@Override
public long getValue() {
return cardinalityValue;
}
private void setValue(long cardinalityValue) {
this.cardinalityValue = cardinalityValue;
}
@Override
protected String getType() {
return CardinalityAggregationBuilder.NAME;
}
private static final ObjectParser<ParsedCardinality, Void> PARSER = new ObjectParser<>(
CardinalityAggregationBuilder.NAME, true, ParsedCardinality::new);
static {
declareCommonFields(PARSER);
PARSER.declareLong(ParsedCardinality::setValue, CommonFields.VALUE);
}
public static ParsedCardinality fromXContent(XContentParser parser, final String name) {
ParsedCardinality cardinality = PARSER.apply(parser, null);
cardinality.setName(name);
return cardinality;
}
@Override
protected XContentBuilder doXContentBody(XContentBuilder builder, Params params)
throws IOException {
builder.field(CommonFields.VALUE.getPreferredName(), cardinalityValue);
return builder;
}
}

View File

@ -98,10 +98,13 @@ public abstract class InternalAggregationTestCase<T extends InternalAggregation>
private T createTestInstance(String name) { private T createTestInstance(String name) {
List<PipelineAggregator> pipelineAggregators = new ArrayList<>(); List<PipelineAggregator> pipelineAggregators = new ArrayList<>();
// TODO populate pipelineAggregators // TODO populate pipelineAggregators
Map<String, Object> metaData = new HashMap<>(); Map<String, Object> metaData = null;
int metaDataCount = randomBoolean() ? 0 : between(1, 10); if (randomBoolean()) {
while (metaData.size() < metaDataCount) { metaData = new HashMap<>();
metaData.put(randomAlphaOfLength(5), randomAlphaOfLength(5)); int metaDataCount = between(0, 10);
while (metaData.size() < metaDataCount) {
metaData.put(randomAlphaOfLength(5), randomAlphaOfLength(5));
}
} }
return createTestInstance(name, pipelineAggregators, metaData); return createTestInstance(name, pipelineAggregators, metaData);
} }

View File

@ -105,7 +105,7 @@ public class ParsedAggregationTests extends ESTestCase {
public static TestParsedAggregation fromXContent(XContentParser parser, String name) throws IOException { public static TestParsedAggregation fromXContent(XContentParser parser, String name) throws IOException {
TestParsedAggregation parsedAgg = PARSER.parse(parser, null); TestParsedAggregation parsedAgg = PARSER.parse(parser, null);
parsedAgg.name = name; parsedAgg.setName(name);
return parsedAgg; return parsedAgg;
} }
} }

View File

@ -19,20 +19,33 @@
package org.elasticsearch.search.aggregations.metrics.cardinality; package org.elasticsearch.search.aggregations.metrics.cardinality;
import org.elasticsearch.common.ParseField;
import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.io.stream.Writeable.Reader; import org.elasticsearch.common.io.stream.Writeable.Reader;
import org.elasticsearch.common.lease.Releasables; import org.elasticsearch.common.lease.Releasables;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.util.MockBigArrays; import org.elasticsearch.common.util.MockBigArrays;
import org.elasticsearch.common.xcontent.NamedXContentRegistry;
import org.elasticsearch.common.xcontent.ToXContent;
import org.elasticsearch.common.xcontent.XContentHelper;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.indices.breaker.NoneCircuitBreakerService; import org.elasticsearch.indices.breaker.NoneCircuitBreakerService;
import org.elasticsearch.rest.action.search.RestSearchAction;
import org.elasticsearch.search.aggregations.Aggregation;
import org.elasticsearch.search.aggregations.InternalAggregationTestCase; import org.elasticsearch.search.aggregations.InternalAggregationTestCase;
import org.elasticsearch.search.aggregations.pipeline.PipelineAggregator; import org.elasticsearch.search.aggregations.pipeline.PipelineAggregator;
import org.junit.After; import org.junit.After;
import org.junit.Before; import org.junit.Before;
import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertToXContentEquivalent;
public class InternalCardinalityTests extends InternalAggregationTestCase<InternalCardinality> { public class InternalCardinalityTests extends InternalAggregationTestCase<InternalCardinality> {
private static List<HyperLogLogPlusPlus> algos; private static List<HyperLogLogPlusPlus> algos;
private static int p; private static int p;
@ -73,6 +86,41 @@ public class InternalCardinalityTests extends InternalAggregationTestCase<Intern
} }
} }
public void testFromXContent() throws IOException {
InternalCardinality cardinality = createTestInstance();
String type = cardinality.getWriteableName();
String name = cardinality.getName();
ToXContent.Params params = new ToXContent.MapParams(Collections.singletonMap(RestSearchAction.TYPED_KEYS_PARAM, "true"));
boolean humanReadable = randomBoolean();
XContentType xContentType = randomFrom(XContentType.values());
BytesReference originalBytes = toShuffledXContent(cardinality, xContentType, params, humanReadable);
ParsedCardinality parsed;
try (XContentParser parser = createParser(xContentType.xContent(), originalBytes)) {
assertEquals(XContentParser.Token.START_OBJECT, parser.nextToken());
assertEquals(XContentParser.Token.FIELD_NAME, parser.nextToken());
assertEquals(type + "#" + name, parser.currentName());
assertEquals(XContentParser.Token.START_OBJECT, parser.nextToken());
parsed = (ParsedCardinality) parser.namedObject(Aggregation.class, type, name);
assertEquals(XContentParser.Token.END_OBJECT, parser.currentToken());
assertEquals(XContentParser.Token.END_OBJECT, parser.nextToken());
assertNull(parser.nextToken());
}
assertEquals(cardinality.getName(), parsed.getName());
assertEquals(cardinality.getValue(), parsed.getValue(), Double.MIN_VALUE);
assertEquals(cardinality.getValueAsString(), parsed.getValueAsString());
assertEquals(cardinality.getMetaData(), parsed.getMetaData());
BytesReference finalAgg = XContentHelper.toXContent(parsed, xContentType, params, humanReadable);
assertToXContentEquivalent(originalBytes, finalAgg, xContentType);
}
@Override
protected NamedXContentRegistry xContentRegistry() {
NamedXContentRegistry.Entry entry = new NamedXContentRegistry.Entry(Aggregation.class,
new ParseField(CardinalityAggregationBuilder.NAME),
(parser, name) -> ParsedCardinality.fromXContent(parser, (String) name));
return new NamedXContentRegistry(Collections.singletonList(entry));
}
@After @After
public void cleanup() { public void cleanup() {
Releasables.close(algos); Releasables.close(algos);