需要ElasticSearch聚合帮助

时间:2018-06-21 11:42:44

标签: elasticsearch elasticsearch-5

目前,我有一个地图领域。我需要汇总唯一键及其值的总和。

例如

   {
        "_index": "inx-flow",
        "_type": "default",
        "_id": "acc4566-23456",
        "_score": 0.0,
        "_source": {
            "@Timestamp": "2018-06-20T09:21:43.892Z",
            "taskType": "typeOne",
            "imageId": "adadiddidd123",
            "taskCreated": "2018-06-20T09:21:43.841Z",
            "scope": {
                "productA": 5
            },
            "taskPriority": 123,
            "taskName": "typeOneName",
            "metrics": {},
            "taskId": "acc4566-23456",
            "taskEvent": "Pending"
        }

}

{

        "_index": "inx-flow",
        "_type": "default",
        "_id": "acc4566-23456",
        "_score": 0.0,
        "_source": {
            "@Timestamp": "2018-06-20T09:21:43.892Z",
            "taskType": "typeOne",
            "imageId": "adadiddidd123",
            "taskCreated": "2018-06-20T09:21:43.841Z",
            "scope": {
                "productA": 1
            },
            "taskPriority": 123,
            "taskName": "typeOneName",
            "metrics": {},
            "taskId": "acc4566-23456",
            "taskEvent": "Pending"
        }
}

{
        "_index": "inx-flow",
        "_type": "default",
        "_id": "acc4566-23456",
        "_score": 0.0,
        "_source": {
            "@Timestamp": "2018-06-20T09:21:43.892Z",
            "taskType": "typeOne",
            "imageId": "adadiddidd123",
            "taskCreated": "2018-06-20T09:21:43.841Z",
            "scope": {
                "productB": 1
            },
            "taskPriority": 123,
            "taskName": "typeOneName",
            "metrics": {},
            "taskId": "acc4566-23456",
            "taskEvent": "Pending"
        }

}

对于上述情况,如果我想跨条目聚合作用域,我希望像ProductA 6 ProductB 1那样聚合。如果对字段名称进行硬核化,但我不希望使用硬编码的值,则可以实现。我的代码

try ( RestHighLevelClient restHighLevelClient = restHighLevelClient()){

        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        LocalDate todayDate = LocalDate.now();
        LocalDate yesterday = todayDate.minusDays(5);
        String toDate = dtf.format(todayDate);
        String fromDate = dtf.format(yesterday);
        SearchRequest searchRequest = new SearchRequest(indexName);
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        searchSourceBuilder.size(10000);
        searchSourceBuilder.query(QueryBuilders.boolQuery().
                filter(QueryBuilders.commonTermsQuery("taskEvent", "Pending")).
                filter(QueryBuilders.rangeQuery("@Timestamp").from(fromDate).to(toDate)));

        TermsAggregationBuilder aggregation = AggregationBuilders.terms("scope")
                .field("scope.productA");
        aggregation.subAggregation(AggregationBuilders.sum("sum")
              .field("scope.productA"));

        searchSourceBuilder.aggregation(aggregation);
        searchRequest.source(searchSourceBuilder);
        SearchResponse searchResponse  = restHighLevelClient.search(searchRequest);

        SearchHit[] hits = searchResponse.getHits().getHits();

        for(SearchHit hit : hits){
            Map responseMap = hit.getSourceAsMap();
            responseMap.forEach((key,value)->
                System.out.println("Key "+key+ " Value "+value));

        }

        System.out.println("**********"+searchResponse.getHits().getHits().length);
        System.out.println("********* " + searchResponse.getAggregations());

        Terms agg = searchResponse.getAggregations().get("scope");
        for(Terms.Bucket bucket : agg.getBuckets()){
            Sum sum = bucket.getAggregations().get("sum");
            System.out.println("Sum " + sum.getValue());
        }
}

您能帮助我了解如何在不对键名进行硬编码的情况下进行汇总吗?就像我想为地图提供根目录,聚合应该基于键及其值

1 个答案:

答案 0 :(得分:0)

我认为唯一可行的方法是首先fetch the mapping并根据映射中给定键的properties集生成聚合列表。

您也可以使用scripted metric aggregation来实现这一点,但是它是实验性的,麻烦的并且可能根本没有效率。

希望有帮助。