From 5a4d7572ac2433a1f5ececd16c2587b6ef6d67ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20B=C3=BCscher?= Date: Mon, 15 May 2017 18:21:12 +0200 Subject: [PATCH 1/2] Add parsing for InternalAdjacencyMatrix --- .../adjacency/ParsedAdjecencyMatrix.java | 123 ++++++++++++++++++ .../aggregations/AggregationsTests.java | 2 + .../InternalAdjacencyMatrixTests.java | 14 +- .../test/InternalAggregationTestCase.java | 3 + 4 files changed, 138 insertions(+), 4 deletions(-) create mode 100644 core/src/main/java/org/elasticsearch/search/aggregations/bucket/adjacency/ParsedAdjecencyMatrix.java diff --git a/core/src/main/java/org/elasticsearch/search/aggregations/bucket/adjacency/ParsedAdjecencyMatrix.java b/core/src/main/java/org/elasticsearch/search/aggregations/bucket/adjacency/ParsedAdjecencyMatrix.java new file mode 100644 index 0000000000000..0e242b57e7ce5 --- /dev/null +++ b/core/src/main/java/org/elasticsearch/search/aggregations/bucket/adjacency/ParsedAdjecencyMatrix.java @@ -0,0 +1,123 @@ +/* + * 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.bucket.adjacency; + +import org.elasticsearch.common.xcontent.ObjectParser; +import org.elasticsearch.common.xcontent.XContentBuilder; +import org.elasticsearch.common.xcontent.XContentParser; +import org.elasticsearch.common.xcontent.XContentParserUtils; +import org.elasticsearch.search.aggregations.Aggregation; +import org.elasticsearch.search.aggregations.Aggregations; +import org.elasticsearch.search.aggregations.ParsedMultiBucketAggregation; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class ParsedAdjecencyMatrix extends ParsedMultiBucketAggregation implements AdjacencyMatrix { + + private Map bucketMap; + + @Override + public String getType() { + return AdjacencyMatrixAggregationBuilder.NAME; + } + + @Override + public List getBuckets() { + return buckets; + } + + @Override + public ParsedBucket getBucketByKey(String key) { + if (bucketMap == null) { + bucketMap = new HashMap<>(buckets.size()); + for (ParsedBucket bucket : buckets) { + bucketMap.put(bucket.getKey(), bucket); + } + } + return bucketMap.get(key); + } + + private static ObjectParser PARSER = + new ObjectParser<>(ParsedAdjecencyMatrix.class.getSimpleName(), true, ParsedAdjecencyMatrix::new); + static { + declareMultiBucketAggregationFields(PARSER, + parser -> ParsedBucket.fromXContent(parser), + parser -> ParsedBucket.fromXContent(parser)); + } + + public static ParsedAdjecencyMatrix fromXContent(XContentParser parser, String name) throws IOException { + ParsedAdjecencyMatrix aggregation = PARSER.parse(parser, null); + aggregation.setName(name); + return aggregation; + } + + public static class ParsedBucket extends ParsedMultiBucketAggregation.ParsedBucket implements AdjacencyMatrix.Bucket { + + private String key; + + @Override + public String getKey() { + return key; + } + + @Override + public String getKeyAsString() { + return key; + } + + @Override + public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { + builder.startObject(); + builder.field(CommonFields.KEY.getPreferredName(), key); + builder.field(CommonFields.DOC_COUNT.getPreferredName(), getDocCount()); + getAggregations().toXContentInternal(builder, params); + builder.endObject(); + return builder; + } + + + static ParsedBucket fromXContent(XContentParser parser) throws IOException { + final ParsedBucket bucket = new ParsedBucket(); + XContentParser.Token token = parser.currentToken(); + String currentFieldName = parser.currentName(); + + List aggregations = new ArrayList<>(); + while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) { + if (token == XContentParser.Token.FIELD_NAME) { + currentFieldName = parser.currentName(); + } else if (token.isValue()) { + if (CommonFields.DOC_COUNT.getPreferredName().equals(currentFieldName)) { + bucket.setDocCount(parser.longValue()); + } else if (CommonFields.KEY.getPreferredName().equals(currentFieldName)) { + bucket.key = parser.text(); + } + } else if (token == XContentParser.Token.START_OBJECT) { + aggregations.add(XContentParserUtils.parseTypedKeysObject(parser, Aggregation.TYPED_KEYS_DELIMITER, Aggregation.class)); + } + } + bucket.setAggregations(new Aggregations(aggregations)); + return bucket; + } + } +} diff --git a/core/src/test/java/org/elasticsearch/search/aggregations/AggregationsTests.java b/core/src/test/java/org/elasticsearch/search/aggregations/AggregationsTests.java index 871cf2756f2fe..fd4b5ae11c2bb 100644 --- a/core/src/test/java/org/elasticsearch/search/aggregations/AggregationsTests.java +++ b/core/src/test/java/org/elasticsearch/search/aggregations/AggregationsTests.java @@ -26,6 +26,7 @@ import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.common.xcontent.XContentType; import org.elasticsearch.rest.action.search.RestSearchAction; +import org.elasticsearch.search.aggregations.bucket.adjacency.InternalAdjacencyMatrixTests; import org.elasticsearch.search.aggregations.bucket.filter.InternalFilterTests; import org.elasticsearch.search.aggregations.bucket.filters.InternalFiltersTests; import org.elasticsearch.search.aggregations.bucket.geogrid.InternalGeoHashGridTests; @@ -124,6 +125,7 @@ private static List getAggsTests() { aggsTests.add(new InternalDateRangeTests()); aggsTests.add(new InternalGeoDistanceTests()); aggsTests.add(new InternalFiltersTests()); + aggsTests.add(new InternalAdjacencyMatrixTests()); return Collections.unmodifiableList(aggsTests); } diff --git a/core/src/test/java/org/elasticsearch/search/aggregations/bucket/adjacency/InternalAdjacencyMatrixTests.java b/core/src/test/java/org/elasticsearch/search/aggregations/bucket/adjacency/InternalAdjacencyMatrixTests.java index 53ae1db4544b1..a7505491e2626 100644 --- a/core/src/test/java/org/elasticsearch/search/aggregations/bucket/adjacency/InternalAdjacencyMatrixTests.java +++ b/core/src/test/java/org/elasticsearch/search/aggregations/bucket/adjacency/InternalAdjacencyMatrixTests.java @@ -21,8 +21,9 @@ import org.elasticsearch.common.io.stream.Writeable.Reader; import org.elasticsearch.search.aggregations.InternalAggregations; +import org.elasticsearch.search.aggregations.InternalMultiBucketAggregationTestCase; +import org.elasticsearch.search.aggregations.ParsedMultiBucketAggregation; import org.elasticsearch.search.aggregations.pipeline.PipelineAggregator; -import org.elasticsearch.test.InternalAggregationTestCase; import org.junit.Before; import java.util.ArrayList; @@ -30,7 +31,7 @@ import java.util.Map; import java.util.TreeMap; -public class InternalAdjacencyMatrixTests extends InternalAggregationTestCase { +public class InternalAdjacencyMatrixTests extends InternalMultiBucketAggregationTestCase { private List keys; @@ -58,12 +59,12 @@ public void setUp() throws Exception { @Override protected InternalAdjacencyMatrix createTestInstance(String name, List pipelineAggregators, - Map metaData) { + Map metaData, InternalAggregations aggregations) { final List buckets = new ArrayList<>(); for (int i = 0; i < keys.size(); ++i) { String key = keys.get(i); int docCount = randomIntBetween(0, 1000); - buckets.add(new InternalAdjacencyMatrix.InternalBucket(key, docCount, InternalAggregations.EMPTY)); + buckets.add(new InternalAdjacencyMatrix.InternalBucket(key, docCount, aggregations)); } return new InternalAdjacencyMatrix(name, buckets, pipelineAggregators, metaData); } @@ -89,4 +90,9 @@ protected void assertReduced(InternalAdjacencyMatrix reduced, List instanceReader() { return InternalAdjacencyMatrix::new; } + + @Override + protected Class implementationClass() { + return ParsedAdjecencyMatrix.class; + } } diff --git a/test/framework/src/main/java/org/elasticsearch/test/InternalAggregationTestCase.java b/test/framework/src/main/java/org/elasticsearch/test/InternalAggregationTestCase.java index 7bd02f82c5e6d..b3862d872ce0a 100644 --- a/test/framework/src/main/java/org/elasticsearch/test/InternalAggregationTestCase.java +++ b/test/framework/src/main/java/org/elasticsearch/test/InternalAggregationTestCase.java @@ -38,6 +38,8 @@ import org.elasticsearch.search.aggregations.Aggregation; import org.elasticsearch.search.aggregations.InternalAggregation; import org.elasticsearch.search.aggregations.ParsedAggregation; +import org.elasticsearch.search.aggregations.bucket.adjacency.AdjacencyMatrixAggregationBuilder; +import org.elasticsearch.search.aggregations.bucket.adjacency.ParsedAdjecencyMatrix; import org.elasticsearch.search.aggregations.bucket.filter.FilterAggregationBuilder; import org.elasticsearch.search.aggregations.bucket.filter.ParsedFilter; import org.elasticsearch.search.aggregations.bucket.filters.FiltersAggregationBuilder; @@ -173,6 +175,7 @@ public abstract class InternalAggregationTestCase map.put(DateRangeAggregationBuilder.NAME, (p, c) -> ParsedDateRange.fromXContent(p, (String) c)); map.put(GeoDistanceAggregationBuilder.NAME, (p, c) -> ParsedGeoDistance.fromXContent(p, (String) c)); map.put(FiltersAggregationBuilder.NAME, (p, c) -> ParsedFilters.fromXContent(p, (String) c)); + map.put(AdjacencyMatrixAggregationBuilder.NAME, (p, c) -> ParsedAdjecencyMatrix.fromXContent(p, (String) c)); namedXContents = map.entrySet().stream() .map(entry -> new NamedXContentRegistry.Entry(Aggregation.class, new ParseField(entry.getKey()), entry.getValue())) From e58a2e8329ade07f1139839de0927d0b128b549e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20B=C3=BCscher?= Date: Tue, 16 May 2017 12:26:03 +0200 Subject: [PATCH 2/2] Adressing review comments --- ...Matrix.java => ParsedAdjacencyMatrix.java} | 47 +++---------------- .../InternalAdjacencyMatrixTests.java | 2 +- .../test/InternalAggregationTestCase.java | 4 +- 3 files changed, 9 insertions(+), 44 deletions(-) rename core/src/main/java/org/elasticsearch/search/aggregations/bucket/adjacency/{ParsedAdjecencyMatrix.java => ParsedAdjacencyMatrix.java} (51%) diff --git a/core/src/main/java/org/elasticsearch/search/aggregations/bucket/adjacency/ParsedAdjecencyMatrix.java b/core/src/main/java/org/elasticsearch/search/aggregations/bucket/adjacency/ParsedAdjacencyMatrix.java similarity index 51% rename from core/src/main/java/org/elasticsearch/search/aggregations/bucket/adjacency/ParsedAdjecencyMatrix.java rename to core/src/main/java/org/elasticsearch/search/aggregations/bucket/adjacency/ParsedAdjacencyMatrix.java index 0e242b57e7ce5..1fb356d45c28c 100644 --- a/core/src/main/java/org/elasticsearch/search/aggregations/bucket/adjacency/ParsedAdjecencyMatrix.java +++ b/core/src/main/java/org/elasticsearch/search/aggregations/bucket/adjacency/ParsedAdjacencyMatrix.java @@ -20,20 +20,15 @@ package org.elasticsearch.search.aggregations.bucket.adjacency; import org.elasticsearch.common.xcontent.ObjectParser; -import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentParser; -import org.elasticsearch.common.xcontent.XContentParserUtils; -import org.elasticsearch.search.aggregations.Aggregation; -import org.elasticsearch.search.aggregations.Aggregations; import org.elasticsearch.search.aggregations.ParsedMultiBucketAggregation; import java.io.IOException; -import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; -public class ParsedAdjecencyMatrix extends ParsedMultiBucketAggregation implements AdjacencyMatrix { +public class ParsedAdjacencyMatrix extends ParsedMultiBucketAggregation implements AdjacencyMatrix { private Map bucketMap; @@ -58,16 +53,16 @@ public ParsedBucket getBucketByKey(String key) { return bucketMap.get(key); } - private static ObjectParser PARSER = - new ObjectParser<>(ParsedAdjecencyMatrix.class.getSimpleName(), true, ParsedAdjecencyMatrix::new); + private static ObjectParser PARSER = + new ObjectParser<>(ParsedAdjacencyMatrix.class.getSimpleName(), true, ParsedAdjacencyMatrix::new); static { declareMultiBucketAggregationFields(PARSER, parser -> ParsedBucket.fromXContent(parser), parser -> ParsedBucket.fromXContent(parser)); } - public static ParsedAdjecencyMatrix fromXContent(XContentParser parser, String name) throws IOException { - ParsedAdjecencyMatrix aggregation = PARSER.parse(parser, null); + public static ParsedAdjacencyMatrix fromXContent(XContentParser parser, String name) throws IOException { + ParsedAdjacencyMatrix aggregation = PARSER.parse(parser, null); aggregation.setName(name); return aggregation; } @@ -86,38 +81,8 @@ public String getKeyAsString() { return key; } - @Override - public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { - builder.startObject(); - builder.field(CommonFields.KEY.getPreferredName(), key); - builder.field(CommonFields.DOC_COUNT.getPreferredName(), getDocCount()); - getAggregations().toXContentInternal(builder, params); - builder.endObject(); - return builder; - } - - static ParsedBucket fromXContent(XContentParser parser) throws IOException { - final ParsedBucket bucket = new ParsedBucket(); - XContentParser.Token token = parser.currentToken(); - String currentFieldName = parser.currentName(); - - List aggregations = new ArrayList<>(); - while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) { - if (token == XContentParser.Token.FIELD_NAME) { - currentFieldName = parser.currentName(); - } else if (token.isValue()) { - if (CommonFields.DOC_COUNT.getPreferredName().equals(currentFieldName)) { - bucket.setDocCount(parser.longValue()); - } else if (CommonFields.KEY.getPreferredName().equals(currentFieldName)) { - bucket.key = parser.text(); - } - } else if (token == XContentParser.Token.START_OBJECT) { - aggregations.add(XContentParserUtils.parseTypedKeysObject(parser, Aggregation.TYPED_KEYS_DELIMITER, Aggregation.class)); - } - } - bucket.setAggregations(new Aggregations(aggregations)); - return bucket; + return parseXContent(parser, false, ParsedBucket::new, (p, bucket) -> bucket.key = p.text()); } } } diff --git a/core/src/test/java/org/elasticsearch/search/aggregations/bucket/adjacency/InternalAdjacencyMatrixTests.java b/core/src/test/java/org/elasticsearch/search/aggregations/bucket/adjacency/InternalAdjacencyMatrixTests.java index a7505491e2626..58c3cc8a22ca3 100644 --- a/core/src/test/java/org/elasticsearch/search/aggregations/bucket/adjacency/InternalAdjacencyMatrixTests.java +++ b/core/src/test/java/org/elasticsearch/search/aggregations/bucket/adjacency/InternalAdjacencyMatrixTests.java @@ -93,6 +93,6 @@ protected Reader instanceReader() { @Override protected Class implementationClass() { - return ParsedAdjecencyMatrix.class; + return ParsedAdjacencyMatrix.class; } } diff --git a/test/framework/src/main/java/org/elasticsearch/test/InternalAggregationTestCase.java b/test/framework/src/main/java/org/elasticsearch/test/InternalAggregationTestCase.java index b3862d872ce0a..99b0046a88702 100644 --- a/test/framework/src/main/java/org/elasticsearch/test/InternalAggregationTestCase.java +++ b/test/framework/src/main/java/org/elasticsearch/test/InternalAggregationTestCase.java @@ -39,7 +39,7 @@ import org.elasticsearch.search.aggregations.InternalAggregation; import org.elasticsearch.search.aggregations.ParsedAggregation; import org.elasticsearch.search.aggregations.bucket.adjacency.AdjacencyMatrixAggregationBuilder; -import org.elasticsearch.search.aggregations.bucket.adjacency.ParsedAdjecencyMatrix; +import org.elasticsearch.search.aggregations.bucket.adjacency.ParsedAdjacencyMatrix; import org.elasticsearch.search.aggregations.bucket.filter.FilterAggregationBuilder; import org.elasticsearch.search.aggregations.bucket.filter.ParsedFilter; import org.elasticsearch.search.aggregations.bucket.filters.FiltersAggregationBuilder; @@ -175,7 +175,7 @@ public abstract class InternalAggregationTestCase map.put(DateRangeAggregationBuilder.NAME, (p, c) -> ParsedDateRange.fromXContent(p, (String) c)); map.put(GeoDistanceAggregationBuilder.NAME, (p, c) -> ParsedGeoDistance.fromXContent(p, (String) c)); map.put(FiltersAggregationBuilder.NAME, (p, c) -> ParsedFilters.fromXContent(p, (String) c)); - map.put(AdjacencyMatrixAggregationBuilder.NAME, (p, c) -> ParsedAdjecencyMatrix.fromXContent(p, (String) c)); + map.put(AdjacencyMatrixAggregationBuilder.NAME, (p, c) -> ParsedAdjacencyMatrix.fromXContent(p, (String) c)); namedXContents = map.entrySet().stream() .map(entry -> new NamedXContentRegistry.Entry(Aggregation.class, new ParseField(entry.getKey()), entry.getValue()))