【问题标题】:Is it possible to group results by a key with Elasticsearch aggregations?是否可以通过 Elasticsearch 聚合的键对结果进行分组?
【发布时间】:2015-09-08 13:51:06
【问题描述】:

我正在尝试执行 Elasticsearch 查询,并希望 Elasticsearch 为我对结果进行分组,而不是让我的客户端代码手动执行。查看 Elasticsearch documentation,我似乎在寻找分桶聚合,但我找不到任何使用它的示例,或者输出看起来像什么以确保这就是我想要的。

我的问题是:是否可以通过 Elasticsearch 中的键对文档进行分组?如果是这样,我如何以及在哪里可以找到有关如何执行此操作的文档,使用查询 DSL 或(最好)Java API 的 Javadoc?

【问题讨论】:

    标签: java elasticsearch


    【解决方案1】:

    我猜你想在elasticsearch中按字段分组,你可以使用Terms aggregation.

    这里是如何使用查询 dsl,

    POST _search 
    {
       "aggs": {
          "genders": {
             "terms": {
                "field": "gender"
             },
             "aggs": {
                "top_tag_hits": {
                   "top_hits": {
                      "_source": {
                         "include": [
                            "include_fields_name"
                         ]
                      },
                      "size": 100
                   }
                }
             }
          }
       }
    }
    

    gender 是文档中的字段, 它的响应可以是

    {
        ...
    
        "aggregations" : {
            "genders" : {
                "buckets" : [
                    {
                        "key" : "male",
                        "doc_count" : 10,
                        "tag_top_hits":{"hits":...}
                    },
                    {
                        "key" : "female",
                        "doc_count" : 10,
                        "tag_top_hits":{"hits":...}
                    },
                ]
            }
        }
    }
    

    使用Java api,我添加了tophits aggregation 以供您发表评论。 (但不在查询 dsl 中)

    client.prepareSearch("index").setTypes("types").addAggregation(
                    AggregationBuilders.terms("agg_name").field("gender").subAggregation(
                            AggregationBuilders.topHits("documents").setSize(10)
                    )
            ).execute(new ActionListener<SearchResponse>() {
                @Override
                public void onResponse(SearchResponse response) {
                    Terms agg_name_aggregation=response.getAggregations().get("agg_name");
                    for (Terms.Bucket bucket : agg_name_aggregation.getBuckets()) {
                        TopHits topHits=bucket.getAggregations().get("documents");
                        System.out.println("term = " + bucket.getKey());
                        // do what you want with top hits..
                    }
                }
    
                @Override
                public void onFailure(Throwable e) {
                    e.printStackTrace();
                }
            });
    

    希望这会有所帮助!

    【讨论】:

    • 谢谢,但这只是给了我匹配文档的计数,而不是文档本身,这是我需要的。
    • 所以你想要不同的男性和女性文档(参考我的例子)? ?
    • 我正在寻找类似 key: male, docs: [list of raw documents where gender is "male"]
    【解决方案2】:

    使用聚合函数分组

        client.prepareSearch(indexName).setTypes(documentType).addAggregation
        (AggregationBuilders.terms("agg_name").field("gender").subAggregation(
        AggregationBuilders.topHits("documents").setSize(10))).execute(new ActionListener<SearchResponse>()
        {
            public void onResponse(SearchResponse response)
            {
    
                Terms agg_name_aggregation=response.getAggregations().get("agg_name");
    
    
                for (Terms.Bucket bucket : agg_name_aggregation.getBuckets())
                {
                    TopHits topHits=bucket.getAggregations().get("documents");
    
                    SearchResponse response1 = client
                            .prepareSearch(indexName)
    
                            .setQuery(QueryBuilders.termQuery("gender",bucket.getKey()))
                            .addAggregation(
                                    AggregationBuilders.max("salary").field(
                                            "salary")).execute().actionGet();
    
                    for (Aggregation avgAggs : response1.getAggregations())
                    {
                        Max avg = (Max) avgAggs;
    
                        double maxValue = avg.getValue();
    
                        System.out.println("Avg Value => " + maxValue);
                    }
    
    
                 //   System.out.println("term = " + bucket.getKey());
    
                 //   System.out.println("count =" + bucket.getDocCount());
    
                  //  System.out.println(topHits.getHits());
    
    
                    for (SearchHit hit: topHits.getHits())
                    {
    
                        System.out.println(hit.getSource());
                    }
    
                }
    
            }
            public void onFailure(Throwable e) {
                e.printStackTrace();
            }
        });
    }
    

    【讨论】:

      猜你喜欢
      • 2019-07-12
      • 1970-01-01
      • 2014-09-08
      • 1970-01-01
      • 2020-02-26
      • 2017-07-26
      • 2012-07-14
      • 2021-01-01
      相关资源
      最近更新 更多