Problem
I am currently trying to combine two aggregations into a single aggregation response either directly in ElasticSearch if it allows or In Java using the elastic aggregations as a map.
Elastic Approach
Mapping
"mappings": {
"properties": {
"Career": {
"type": "nested",
"properties": {
"Pro": {
"type": "nested",
"properties": {
"teamName" :{
"type": "keyword"
},
"position": {
"type": "keyword"
},
"positionId": {
"type": "keyword"
},
"positionsubtype": {
"type": "keyword"
},
"positionsubtypeId": {
"type": "keyword"
}
}
},
"College": {
"type": "nested",
"properties": {
"teamName" :{
"type": "keyword"
},
"position": {
"type": "keyword"
},
"positionId": {
"type": "keyword"
},
"positionsubtype": {
"type": "keyword"
},
"positionsubtypeId": {
"type": "keyword"
}
}
},
"High School": {
"type": "nested",
"properties": {
"teamName" :{
"type": "keyword"
},
"position": {
"type": "keyword"
},
"positionId": {
"type": "keyword"
},
"positionsubtype": {
"type": "keyword"
},
"positionsubtypeId": {
"type": "keyword"
}
}
}
}
},
"Name": {
"type": "nested",
"properties": {
"Firstname": {
"type": "keyword"
},
"Suffix": {
"type": "keyword"
},
"Surname": {
"type": "keyword"
}
}
}
}
}
Query
{
"query": {
"nested": {
"path": "Name",
"query": {
"match": {
"Name.Firstname": "Odell"
}
}
}
},
"aggs": {
"Pro Career": {
"nested": {
"path": "Career.Pro"
},
"aggs": {
"Positions": {
"terms": {
"field": "Career.Pro.position",
"size": 10
},
"aggs": {
"Position SubType": {
"terms": {
"field": "Career.Pro.positionsubtype",
"size": 10
}
}
}
}
}
},
"College Career": {
"nested": {
"path": "Career.College"
},
"aggs": {
"Positions": {
"terms": {
"field": "Career.College.position",
"size": 10
},
"aggs": {
"Position SubType": {
"terms": {
"field": "Career.College.positionsubtype",
"size": 10
}
}
}
}
}
}
}
}
Response
"aggregations": {
"Pro Career": {
"doc_count": 2,
"Positions": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [
{
"key": "Wide Receiver",
"doc_count": 2,
"Position SubType": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [
{
"key": "First String",
"doc_count": 2
}
]
}
}
]
}
},
"College Career": {
"doc_count": 1,
"Positions": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [
{
"key": "Wide Receiver",
"doc_count": 1,
"Position SubType": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [
{
"key": "Second String",
"doc_count": 1
}
]
}
}
]
}
}
}
Java Approach
public Map<String, Aggregation> combineAggregations() throws IOException {
Collection<AggregationBuilder> aggregationBuilders = new ArrayList<>();
aggregationBuilders.add(
AggregationBuilders.nested("Pro Career","Career.Pro")
.subAggregation(AggregationBuilders.terms("Positions").field("Career.Pro.position")
.subAggregation(AggregationBuilders.terms("Positions SubType").field("Career.Pro.positionsubtype")
.subAggregation(AggregationBuilders.topHits("Aggregation hit")))));
aggregationBuilders.add(
AggregationBuilders.nested("College Career","Career.College")
.subAggregation(AggregationBuilders.terms("Positions").field("Career.College.position")
.subAggregation(AggregationBuilders.terms("Positions SubType").field("Career.College.positionsubtype")
.subAggregation(AggregationBuilders.topHits("Aggregation hit")))));
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
SearchRequest searchRequest = new SearchRequest();
searchSourceBuilder.query(nestedQuery("Name", matchQuery("Name.Firstname","Odell"), ScoreMode.Avg));
aggregationBuilders.forEach(searchSourceBuilder::aggregation);
searchRequest.source(searchSourceBuilder).indices("player");
SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
Map<String,Aggregation> proAggregationMap = new HashMap<>();
Map<String,Aggregation> collegeAggregationMap = new HashMap<>();
searchResponse.getAggregations().getAsMap().forEach((s, aggregation) ->{
if (s.equalsIgnoreCase("Pro Career")){
Nested nested = (Nested) aggregation;
nested.getAggregations().getAsMap().forEach(
proAggregationMap::put
);
}
if (s.equalsIgnoreCase("College Career")){
Nested nested = (Nested) aggregation;
nested.getAggregations().getAsMap().forEach(
collegeAggregationMap::put
);
}
});
Map<String,Aggregation> careerAggregationMap = Stream.concat(
proAggregationMap.entrySet().stream(),collegeAggregationMap.entrySet().stream()).collect(
Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
log.info(String.valueOf(careerAggregationMap));
return careerAggregationMap;
}
Java Error
When merging the two Maps i get the current error as i currently don't have a merger to handle the two duplicate aggregations.
java.lang.IllegalStateException: Duplicate key org.elasticsearch.search.aggregations.bucket.terms.ParsedStringTerms@360938db
Any help to resolve this would be great
Thank you