Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.util.BigArrays;
import org.elasticsearch.common.xcontent.AbstractObjectParser;
import org.elasticsearch.common.xcontent.ToXContent;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.rest.action.search.RestSearchAction;
Expand Down Expand Up @@ -193,6 +194,11 @@ public final XContentBuilder toXContent(XContentBuilder builder, Params params)
return builder;
}

protected static void declareCommonField(AbstractObjectParser<Map<String, Object>, Void> parser) {
parser.declareObject((map, metaMap) -> map.put(CommonFields.META.getPreferredName(), metaMap),
(p, c) -> p.map(), CommonFields.META);
}

public abstract XContentBuilder doXContentBody(XContentBuilder builder, Params params) throws IOException;

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,18 @@
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.util.BigArrays;
import org.elasticsearch.common.xcontent.ObjectParser;
import org.elasticsearch.common.xcontent.ToXContent;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.search.DocValueFormat;
import org.elasticsearch.search.aggregations.Aggregation;
import org.elasticsearch.search.aggregations.InternalAggregation;
import org.elasticsearch.search.aggregations.metrics.InternalNumericMetricsAggregation;
import org.elasticsearch.search.aggregations.pipeline.PipelineAggregator;

import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

Expand Down Expand Up @@ -127,4 +132,79 @@ protected boolean doEquals(Object obj) {
HyperLogLogPlusPlus getState() {
return counts;
}
private static final ObjectParser<Map<String, Object>, Void> PARSER = new ObjectParser<>(
"internal_cardinality", true, () -> new HashMap<>());

static {
declareCommonField(PARSER);
PARSER.declareLong((map, value) -> map.put(CommonFields.VALUE.getPreferredName(), value),
CommonFields.VALUE);
}

public static Cardinality parseXContentBody(final String name, XContentParser parser) {
Map<String, Object> map = PARSER.apply(parser, null);
final long cardinalityValue = (Long) map.getOrDefault(CommonFields.VALUE.getPreferredName(),
Double.POSITIVE_INFINITY);
@SuppressWarnings("unchecked")
final Map<String, Object> metaData = (Map<String, Object>) map
.get(CommonFields.META.getPreferredName());
return new ParsedCardinality(name, cardinalityValue, metaData);
}

private static class ParsedCardinality implements Aggregation, Cardinality, ToXContent {

private long cardinalityValue;
private String name;
private Map<String, Object> medadata;

ParsedCardinality(String name, long cardinality, Map<String, Object> metaData) {
this.cardinalityValue = cardinality;
this.name = name;
this.medadata = metaData;
}

@Override
public double value() {
return getValue();
}

@Override
public String getValueAsString() {
return DocValueFormat.RAW.format(value());
}

@Override
public String getName() {
return name;
}

@Override
public Object getProperty(String path) {
if (path.isEmpty()) {
return this;
} else if ("value".equals(path)) {
return value();
} else {
throw new IllegalArgumentException(
"path not supported for [" + getName() + "]: " + path);
}
}

@Override
public Map<String, Object> getMetaData() {
return this.medadata;
}

@Override
public long getValue() {
return cardinalityValue;
}

@Override
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
builder.field(CommonFields.VALUE.getPreferredName(), cardinalityValue);
return builder;
}
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -19,20 +19,29 @@

package org.elasticsearch.search.aggregations.metrics.cardinality;

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.ToXContent;
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.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.common.xcontent.XContentHelper.toXContent;

public class InternalCardinalityTests extends InternalAggregationTestCase<InternalCardinality> {
private static List<HyperLogLogPlusPlus> algos;
private static int p;
Expand Down Expand Up @@ -73,6 +82,30 @@ protected void assertReduced(InternalCardinality reduced, List<InternalCardinali
}
}

public void testFromXContent() throws IOException {
InternalCardinality cardinality = createTestInstance();
ToXContent.Params params = new ToXContent.MapParams(Collections.singletonMap(RestSearchAction.TYPED_KEYS_PARAM, "true"));
boolean humanReadable = randomBoolean();
XContentType xContentType = randomFrom(XContentType.values());
BytesReference originalBytes = toXContent(cardinality, xContentType, params, humanReadable);

Cardinality parsed;
try (XContentParser parser = createParser(xContentType.xContent(), originalBytes)) {
assertEquals(XContentParser.Token.START_OBJECT, parser.nextToken());
assertEquals(XContentParser.Token.FIELD_NAME, parser.nextToken());
assertEquals(cardinality.getWriteableName() + "#" + cardinality.getName(), parser.currentName());
assertEquals(XContentParser.Token.START_OBJECT, parser.nextToken());
parsed = InternalCardinality.parseXContentBody(cardinality.getName(), parser);
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());
}

@After
public void cleanup() {
Releasables.close(algos);
Expand Down