如何将scriptedMetric聚合嵌套到elasticsearch的java api中的术语聚合中?

时间:2017-11-18 14:05:38

标签: elasticsearch elasticsearch-aggregation

我想使用Elasticsearch的聚合来进行OLAP数据分析。 我想要做的是将一个scriptedMetric聚合嵌套到一个术语聚合中,如下所示(它是正确的)

{
    "from": 0,
    "size": 0,
  "query":{
    "bool":{
      "must":[
        {
          "match":{
            "poi_id":1
          }
        }
        ]
    }
  },
    "aggregations": {
        "poi_id": {
            "terms": {
                "script": {
                    "inline": "doc['poi_id'].value + 1"
                }
            },
            "aggregations": {
                "price": {
                    "sum": {
                        "field": "price"
                    }
                }
            }
        }
    }
}

但我在Elasticsearch的java api中找不到如何做到这一点。

我已经这样试过了:

SearchResponse response = client.prepareSearch("poi")
        .setSearchType(SearchType.DFS_QUERY_THEN_FETCH)
        .setFetchSource(new String[]{"poi_id","poi_name"}, null)
        .setQuery(QueryBuilders.termQuery("poi_id", 1))
        .addAggregation(AggregationBuilders.terms("poi_id").subAggregation((AggregationBuilders.scriptedMetric("poi_id").mapScript(new Script("doc['poi_id'].value + 1")))))
        .execute()
        .actionGet();

但是出错了

Caused by: NotSerializableExceptionWrapper[: value source config is invalid; must have either a field context or a script or marked as unwrapped]; nested: IllegalStateException[value source config is invalid; must have either a field context or a script or marked as unwrapped];

我经常搜索,但无法找到演示。

任何帮助都将不胜感激。

谢谢!

1 个答案:

答案 0 :(得分:0)

    @Override
public Map<String, Object> sumPriceAggregation(String field, int page, int size) {
    if (StringUtils.isEmpty(field)) {
        field = "brandName";
    }
    NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
    PageRequest pageRequest = PageRequest.of(page, size);
    queryBuilder.withPageable(pageRequest);
    queryBuilder.withSourceFilter(new FetchSourceFilter(new String[] {""}, null));
    String termStr = field.toUpperCase();
    TermsAggregationBuilder termsAggregationBuilder = AggregationBuilders.terms(termStr)
            .field(field)
            .subAggregation(AggregationBuilders.sum("totalPrice").field("price")); //be aware this is subAggregation
    NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
    nativeSearchQueryBuilder.addAggregation(termsAggregationBuilder);
    AggregatedPage<GamingLaptop> aggregatedPage = elasticsearchRestTemplate.queryForPage(
            nativeSearchQueryBuilder.build(), GamingLaptop.class);
    Aggregations aggregations = aggregatedPage.getAggregations();
    ParsedStringTerms stringTerms = aggregations.get(termStr);
    List<? extends Terms.Bucket> buckets = stringTerms.getBuckets();
    HashMap<String, Object> map = new HashMap<>();
    buckets.parallelStream().forEach(bucket -> {
        String key = bucket.getKeyAsString();
        long docCount = bucket.getDocCount();
        map.put(key, docCount);
        ParsedSum sum = (ParsedSum) bucket.getAggregations().asMap().get("totalPrice"); //make sure you get the aggregation here
        map.putIfAbsent("sum", sum.getValue());
    });
    return map;
}

'值源配置无效;必须具有字段上下文或脚本或标记为“未包装”。我也遇到此错误,请阅读代码中的注释,这是我的解决方案。需要检索 ParsedStringTerms TermsAggregationBuilder