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);
|
||||
}
|
||||
|
||||
String name;
|
||||
private String name;
|
||||
Map<String, Object> metadata;
|
||||
|
||||
@Override
|
||||
|
@ -46,6 +46,10 @@ public abstract class ParsedAggregation implements Aggregation, ToXContent {
|
|||
return name;
|
||||
}
|
||||
|
||||
protected void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Map<String, Object> getMetaData() {
|
||||
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
|
||||
protected abstract String getType();
|
||||
|
||||
@Override
|
||||
public XContentBuilder toXContent(XContentBuilder builder, ToXContent.Params params) throws IOException {
|
||||
// Concatenates the type and the name of the aggregation (ex: top_hits#foo)
|
||||
builder.startObject(String.join(InternalAggregation.TYPED_KEYS_DELIMITER, getType(), name));
|
||||
|
|
|
@ -128,3 +128,4 @@ public final class InternalCardinality extends InternalNumericMetricsAggregation
|
|||
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,11 +98,14 @@ public abstract class InternalAggregationTestCase<T extends InternalAggregation>
|
|||
private T createTestInstance(String name) {
|
||||
List<PipelineAggregator> pipelineAggregators = new ArrayList<>();
|
||||
// TODO populate pipelineAggregators
|
||||
Map<String, Object> metaData = new HashMap<>();
|
||||
int metaDataCount = randomBoolean() ? 0 : between(1, 10);
|
||||
Map<String, Object> metaData = null;
|
||||
if (randomBoolean()) {
|
||||
metaData = new HashMap<>();
|
||||
int metaDataCount = between(0, 10);
|
||||
while (metaData.size() < metaDataCount) {
|
||||
metaData.put(randomAlphaOfLength(5), randomAlphaOfLength(5));
|
||||
}
|
||||
}
|
||||
return createTestInstance(name, pipelineAggregators, metaData);
|
||||
}
|
||||
|
||||
|
|
|
@ -105,7 +105,7 @@ public class ParsedAggregationTests extends ESTestCase {
|
|||
|
||||
public static TestParsedAggregation fromXContent(XContentParser parser, String name) throws IOException {
|
||||
TestParsedAggregation parsedAgg = PARSER.parse(parser, null);
|
||||
parsedAgg.name = name;
|
||||
parsedAgg.setName(name);
|
||||
return parsedAgg;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,20 +19,33 @@
|
|||
|
||||
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.lease.Releasables;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
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.rest.action.search.RestSearchAction;
|
||||
import org.elasticsearch.search.aggregations.Aggregation;
|
||||
import org.elasticsearch.search.aggregations.InternalAggregationTestCase;
|
||||
import org.elasticsearch.search.aggregations.pipeline.PipelineAggregator;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertToXContentEquivalent;
|
||||
|
||||
public class InternalCardinalityTests extends InternalAggregationTestCase<InternalCardinality> {
|
||||
private static List<HyperLogLogPlusPlus> algos;
|
||||
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
|
||||
public void cleanup() {
|
||||
Releasables.close(algos);
|
||||
|
|
Loading…
Reference in New Issue