2017-02-20 32 views
0

我试图解析从弹性搜索返回到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”

请帮忙。

+0

我建议你使用[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

+0

@Val或作为Jest的替代品,他可以使用官方的低级Java-REST客户端:https://www.elastic.co/guide/en/elasticsearch/client/java-rest/current/java-rest。 html – JonyD

+0

@JonyD低级别的REST客户端仅适用于ES 5以上版本,所以如果他运行的话,那么确定。最后,他可以使用他觉得最舒适的任何东西,现在他有三种选择;-) – Val

回答

0

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

我知道这看起来有点笨拙,但可能会为你的情况。否则让我知道。