【问题标题】:Parse Incoming JSON directly into DTO with dynamic key使用动态密钥将传入的 JSON 直接解析为 DTO
【发布时间】:2017-02-20 06:29:47
【问题描述】:

我正在尝试将从 Elastic 搜索返回的数据解析为 java 类。弹性搜索以下面给出的形式返回数据:

"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" 的这个问题?

请帮忙。

【问题讨论】:

  • 我建议你使用Jest或者官方的Java client,两者都会将聚合结果解析成可以探索的地图。
  • @Val 或者作为 Jest 的替代品,他可以使用官方的低级 Java-REST 客户端:elastic.co/guide/en/elasticsearch/client/java-rest/current/…
  • @JonyD 低级 REST 客户端仅适用于 ES 5 及更高版本,因此如果他运行该客户端,则可以。最后,他可以使用他觉得最舒服的任何东西,现在他有三个选择;-)

标签: java json spring elasticsearch dto


【解决方案1】:

前段时间我偶然发现了同样的问题,不幸的是,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;
}

我知道这看起来有点笨拙,但可能适合您的情况。否则请告诉我。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-08-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-16
    • 2016-03-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多