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:
parent
f538d7b8d6
commit
356532816a
|
@ -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;
|
||||||
}
|
}
|
|
@ -128,3 +128,4 @@ public final class InternalCardinality extends InternalNumericMetricsAggregation
|
||||||
return counts;
|
return counts;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue