有没有办法按聚合进行分组并获取属于特定组聚合的所有文档?

时间:2017-10-10 01:02:23

标签: elasticsearch

有没有办法按聚合进行分组并获取属于特定组聚合的所有文档?

所以这不像聚合分组,对于每个组,您获得一些聚合/度量,但我也希望在一个查询中导致特定组聚合的所有记录。今天ES有可能吗?

例如:

输入数据集

{"name": "foo", "amount": 5, "city":"san francisco",  "state": "CA"}
{"name": "foo", "amount": 10, "city":"Los angeles",  "state": "CA"}
{"name": "bar", "amount": 20, "city":"Austin",  "state": "TX"}

现在说我想按名称和状态进行分组,并获得每个组的“金额”和计数的总和以及导致汇总结果的记录本身。所以预期的输出是这样的

预期产出:

[
    {group: {"name": "foo", "state": "CA"}, "amount": 15, "count": 2, "docs": [{"name": "foo", "amount": 5, "city":"san francisco",  "state": "CA"}, {"name": "foo", "amount": 10, "city":"Los angeles",  "state": "CA"}]}, 
    {group: {"name": "bar", "state": "TX"}, "amount": 20, "count": 1, "docs": [{"name": "bar", "amount": 20, "city":"Austin",  "state": "TX"}]}
]

ES 5.0很好。

1 个答案:

答案 0 :(得分:1)

您可以使用子聚合的组合来按指标获取所有组,但尝试获取作为聚合的一部分返回的匹配是一个坏主意。对于您正在进行分组的N个文档,您基本上要求Elasticsearch返回每个文档,这些文档首先会破坏聚合的目的。

您正在“分组”的每个字段(在ES术语中,术语聚合)需要是它自己的聚合,但您可以无限地嵌套它们,并根据您定义的分组数量以编程方式序列化和反序列化结果。确保您的字词字段是“关键字”类型!

此查询将为您提供所需的所有指标 - 您只需要展平结果应用程序端:

{
    "aggs" : {
    "by_name" : {
        "terms" : { "field" : "name" },
        "aggs" : {
        "by_state" : {
            "terms" : { "field" : "state" },
            "aggs" : {
            "total_amount" : { "sum" : { "field" : "amount" } }
            }
        }
        }
    }
    }
}

如果您确实需要这些文档,是否可以使用术语过滤器动态加载它们?或者,如果确实需要破解它并且您了解数据的分布,则可以使用top_hits sub aggregation返回文档。请注意,每个额外的子聚合,尤其是热门命中,都会影响性能。