mirror of
https://github.com/honeymoose/OpenSearch.git
synced 2025-02-08 14:05:27 +00:00
Add ParsedAggregation as base Aggregation impl for high level client
ParsedAggregation is the base Aggregation implementation for the high level client, which parses aggs responses into java objects.
This commit is contained in:
parent
e156dbaf42
commit
420fa8c400
@ -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;
|
||||
|
||||
import org.elasticsearch.common.xcontent.ObjectParser;
|
||||
import org.elasticsearch.common.xcontent.ToXContent;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* An implementation of {@link Aggregation} that is parsed from a REST response.
|
||||
* Serves as a base class for all aggregation implementations that are parsed from REST.
|
||||
*/
|
||||
public abstract class ParsedAggregation implements Aggregation, ToXContent {
|
||||
|
||||
//TODO move CommonFields out of InternalAggregation
|
||||
protected static void declareCommonFields(ObjectParser<? extends ParsedAggregation, Void> objectParser) {
|
||||
objectParser.declareObject((parsedAgg, metadata) -> parsedAgg.metadata.putAll(metadata),
|
||||
(parser, context) -> parser.map(), InternalAggregation.CommonFields.META);
|
||||
}
|
||||
|
||||
String name;
|
||||
final Map<String, Object> metadata = new HashMap<>();
|
||||
|
||||
@Override
|
||||
public final String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Map<String, Object> getMetaData() {
|
||||
return Collections.unmodifiableMap(metadata);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string representing the type of the aggregation. This type is added to
|
||||
* the aggregation name in the response, so that it can later be used by REST clients
|
||||
* to determine the internal type of the aggregation.
|
||||
*/
|
||||
//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();
|
||||
|
||||
//TODO the only way to avoid duplicating this method is making Aggregation extend ToXContent
|
||||
//and declare toXContent as a default method in it. Doesn't sound like the right thing to do.
|
||||
public XContentBuilder toXContent(XContentBuilder builder, ToXContent.Params params) throws IOException {
|
||||
//TODO move TYPED_KEYS_DELIMITER constant out of InternalAggregation
|
||||
// Concatenates the type and the name of the aggregation (ex: top_hits#foo)
|
||||
builder.startObject(String.join(InternalAggregation.TYPED_KEYS_DELIMITER, getType(), name));
|
||||
if (metadata.isEmpty() == false) {
|
||||
builder.field(InternalAggregation.CommonFields.META.getPreferredName());
|
||||
builder.map(metadata);
|
||||
}
|
||||
doXContentBody(builder, params);
|
||||
builder.endObject();
|
||||
return builder;
|
||||
}
|
||||
|
||||
protected abstract XContentBuilder doXContentBody(XContentBuilder builder, Params params) throws IOException;
|
||||
}
|
@ -0,0 +1,145 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import org.elasticsearch.common.ParseField;
|
||||
import org.elasticsearch.common.bytes.BytesReference;
|
||||
import org.elasticsearch.common.io.stream.StreamOutput;
|
||||
import org.elasticsearch.common.xcontent.NamedXContentRegistry;
|
||||
import org.elasticsearch.common.xcontent.ObjectParser;
|
||||
import org.elasticsearch.common.xcontent.ToXContent;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.common.xcontent.XContentHelper;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.common.xcontent.XContentType;
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
import org.elasticsearch.test.rest.FakeRestRequest;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertToXContentEquivalent;
|
||||
import static org.hamcrest.CoreMatchers.instanceOf;
|
||||
|
||||
public class ParsedAggregationTests extends ESTestCase {
|
||||
|
||||
//TODO maybe this test will no longer be needed once we have real tests for ParsedAggregation subclasses
|
||||
public void testParse() throws IOException {
|
||||
String name = randomAlphaOfLengthBetween(5, 10);
|
||||
int numMetas = randomIntBetween(0, 5);
|
||||
Map<String, Object> meta = new HashMap<>(numMetas);
|
||||
for (int i = 0; i < numMetas; i++) {
|
||||
meta.put(randomAlphaOfLengthBetween(3, 10), randomAlphaOfLengthBetween(3, 10));
|
||||
}
|
||||
TestInternalAggregation testAgg = new TestInternalAggregation(name, meta);
|
||||
XContentType xContentType = randomFrom(XContentType.values());
|
||||
FakeRestRequest params = new FakeRestRequest.Builder(NamedXContentRegistry.EMPTY)
|
||||
.withParams(Collections.singletonMap("typed_keys", "true")).build();
|
||||
BytesReference bytesAgg = XContentHelper.toXContent(testAgg, xContentType, params, randomBoolean());
|
||||
try (XContentParser parser = createParser(xContentType.xContent(), bytesAgg)) {
|
||||
parser.nextToken();
|
||||
assert parser.currentToken() == XContentParser.Token.START_OBJECT;
|
||||
parser.nextToken();
|
||||
assert parser.currentToken() == XContentParser.Token.FIELD_NAME;
|
||||
String currentName = parser.currentName();
|
||||
int i = currentName.indexOf(InternalAggregation.TYPED_KEYS_DELIMITER);
|
||||
String aggType = currentName.substring(0, i);
|
||||
String aggName = currentName.substring(i + 1);
|
||||
Aggregation parsedAgg = parser.namedObject(Aggregation.class, aggType, aggName);
|
||||
assertThat(parsedAgg, instanceOf(TestParsedAggregation.class));
|
||||
assertEquals(testAgg.getName(), parsedAgg.getName());
|
||||
assertEquals(testAgg.getMetaData(), parsedAgg.getMetaData());
|
||||
BytesReference finalAgg = XContentHelper.toXContent((ToXContent) parsedAgg, xContentType, randomBoolean());
|
||||
assertToXContentEquivalent(bytesAgg, finalAgg, xContentType);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected NamedXContentRegistry xContentRegistry() {
|
||||
//TODO we may want to un-deprecate this Entry constructor if we are going to use it extensively, which I think we are
|
||||
NamedXContentRegistry.Entry entry = new NamedXContentRegistry.Entry(Aggregation.class, new ParseField("type"),
|
||||
(parser, name) -> TestParsedAggregation.fromXContent(parser, (String)name));
|
||||
return new NamedXContentRegistry(Collections.singletonList(entry));
|
||||
}
|
||||
|
||||
private static class TestParsedAggregation extends ParsedAggregation {
|
||||
private static ObjectParser<TestParsedAggregation, Void> PARSER = new ObjectParser<>("testAggParser", TestParsedAggregation::new);
|
||||
|
||||
static {
|
||||
ParsedAggregation.declareCommonFields(PARSER);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getType() {
|
||||
return "type";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected XContentBuilder doXContentBody(XContentBuilder builder, Params params) throws IOException {
|
||||
return builder;
|
||||
}
|
||||
|
||||
public static TestParsedAggregation fromXContent(XContentParser parser, String name) throws IOException {
|
||||
TestParsedAggregation parsedAgg = PARSER.parse(parser, null);
|
||||
parsedAgg.name = name;
|
||||
return parsedAgg;
|
||||
}
|
||||
}
|
||||
|
||||
private static class TestInternalAggregation extends InternalAggregation {
|
||||
|
||||
private TestInternalAggregation(String name, Map<String, Object> metaData) {
|
||||
super(name, Collections.emptyList(), metaData);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getWriteableName() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getType() {
|
||||
return "type";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doWriteTo(StreamOutput out) throws IOException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public InternalAggregation doReduce(List<InternalAggregation> aggregations, ReduceContext reduceContext) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getProperty(List<String> path) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public XContentBuilder doXContentBody(XContentBuilder builder, Params params) throws IOException {
|
||||
return builder;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user