使用动态密钥直接解析传入的JSON到DTO
问题描述:
我试图解析从弹性搜索返回到java类的数据。弹性搜索返回如下形式的数据:使用动态密钥直接解析传入的JSON到DTO
"aggregations": {
"aggregationName": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [
{
"key": 439,
"doc_count": 7,
"nestedAggregationName": {
"value": 5
}
}
]
}
}
这里的“aggregationName”和“nestedAggregationName”名称是动态的,意味着它们可以是任何东西,所以我怎么能管理,这是我的课?我想直接解析返回到DTO中的数据。
编辑:我能够做出如下一类以一般的方式来解析“aggregationName”:
public Class Aggregation{
private Map<String, AggregationModel> aggregation;
//with getters and setters.
}
所以无论“aggregationName”是,它很容易被解析并AggregationModel包含与“aggregationName”对应的字段。我如何解决这个问题“nestedAggregationName”?
请帮忙。
答
我偶然发现了同样的问题,不幸的是,java客户端不支持聚合响应(请纠正我,如果我错了)。 以下是经过多轮追踪误差处理后我想出的,让我知道这是否有帮助。
private Map<String, List<Map.Entry<String, Long>>> buildAggregationsFromResult(SearchResults resultSet, Set aggregationsName) {
Map<String, List<Map.Entry<String, Long>>> aggregations = new LinkedHashMap<String, List<Map.Entry<String, Long>>>();
if (null != resultSet.getAggregations()) {
Map<String, Aggregation> aggregationMap = resultSet.getAggregations().asMap();
for (Map.Entry<String, Aggregation> aggregationEntry : aggregationMap.entrySet()) {
fetchBucketTermsFromAggregations(aggregationEntry,aggregations, aggregationsName);
}
}
return aggregations;
}
private List<Map.Entry<String, Long>> fetchBucketTermsFromAggregations(Map.Entry<String, Aggregation> aggregationEntry, Map<String, List<Map.Entry<String, Long>>> aggregations, Set<String> aggregationsName) {
Terms terms = null;
List<Map.Entry<String, Long>> pairs = new ArrayList<>();
if (aggregationEntry.getValue() instanceof InternalNested) {
for (Map.Entry<String, Aggregation> aggregationEntryNested : ((InternalNested) aggregationEntry.getValue()).getAggregations().asMap().entrySet()) {
pairs = fetchBucketTermsFromAggregations(aggregationEntryNested, aggregations, aggregationsName);
if (CollectionUtils.isNotEmpty(pairs) && aggregationsName.contains(aggregationEntry.getKey()))
aggregations.put(aggregationEntry.getKey(), pairs);
}
} else if (aggregationEntry.getValue() instanceof InternalFilters) {
for (InternalFilters.Bucket buckets : ((InternalFilters) aggregationEntry.getValue()).getBuckets()) {
for (Map.Entry<String, Aggregation> nestedAggregations : buckets.getAggregations().asMap().entrySet()) {
pairs = fetchBucketTermsFromAggregations(nestedAggregations, aggregations, aggregationsName);
if (CollectionUtils.isNotEmpty(pairs) && aggregationsName.contains(aggregationEntry.getKey()))
aggregations.put(aggregationEntry.getKey(), pairs);
}
}
} else {
terms = (Terms) aggregationEntry.getValue();
if (null != terms) {
Collection<Terms.Bucket> buckets = terms.getBuckets();
for (Terms.Bucket bucket : buckets) {
if (CollectionUtils.isNotEmpty(bucket.getAggregations().asList()))
pairs.add(new AbstractMap.SimpleEntry<String, Long>(bucket.getKeyAsString(), ((InternalReverseNested)bucket.getAggregations().asList().get(0)).getDocCount()));
else
pairs.add(new AbstractMap.SimpleEntry<String, Long>(bucket.getKeyAsString(), bucket.getDocCount()));
}
}
if (CollectionUtils.isNotEmpty(pairs) && aggregationsName.contains(aggregationEntry.getKey()))
aggregations.put(aggregationEntry.getKey(), pairs);
}
return pairs;
}
我知道这看起来有点笨拙,但可能会为你的情况。否则让我知道。
我建议你使用[Jest](https://github.com/searchbox-io/Jest/tree/master/jest)或官方的[Java客户端](https://www.elastic.co/guide /en/elasticsearch/client/java-api/current/index.html),这两者都会将聚合结果解析为可探索的地图。 – Val
@Val或作为Jest的替代品,他可以使用官方的低级Java-REST客户端:https://www.elastic.co/guide/en/elasticsearch/client/java-rest/current/java-rest。 html – JonyD
@JonyD低级别的REST客户端仅适用于ES 5以上版本,所以如果他运行的话,那么确定。最后,他可以使用他觉得最舒适的任何东西,现在他有三种选择;-) – Val