如何在 ElasticSearch 中展平深度聚合?
How can I flatten a deep aggregation in ElasticSearch?
我的索引中有这样的文档:
{
"foo": null,
"bars": [
{
"baz": "BAZ",
"qux": null,
"bears": [
{
"fruit": "banana"
}
]
}
]
}
我想将 .bars[].bears[].fruit
的唯一值与每个找到的值的计数相加。但是,我也只想计算在 foo
上匹配特定条件的文档的这些深度值,以及在 baz
和 qux
上匹配特定条件的 bars[]
的值。我还想汇总所有文档,忽略搜索查询恰好是什么。
下面的查询完成了我想做的一切:
{
"aggs": {
"global": {
"global": {},
"aggs": {
"notFoo": {
"filter": {
"bool": {
"must_not": [
{
"exists": {
"field": "foo"
}
}
]
}
},
"aggs": {
"bars": {
"nested": {
"path": "bars"
},
"aggs": {
"notValueN": {
"filter": {
"bool": {
"filter": [
{
"bool": {
"should": [
{
"terms": {
"bars.baz": [
"value1",
"value2",
"value3"
]
}
},
{
"terms": {
"bars.qux": [
"value4",
"value5",
"value6"
]
}
}
],
"minimum_should_match": 1
}
}
]
}
},
"aggs": {
"bears": {
"nested": {
"path": "bars.bears"
},
"aggs": {
"rules": {
"terms": {
"field": "bars.bears.fruit"
}
}
}
}
}
}
}
}
}
}
}
}
}
}
此查询有效,但感觉相当庞大和繁重。为了从响应中获得我正在寻找的结果,我必须访问 .aggregations.global.bars.notValueN.bears.fruit.buckets
。有没有办法展平这个大查询?就目前而言,如果以后需要引入任何其他条件,则此查询很难维护。
ES 唯一支持 object key flattening 的地方是集群设置 API。遗憾的是,此策略 不能 用于 API 的其他部分,包括聚合。
不过,还有一些其他技巧值得一提。
1。首先是聚合元数据。
任何负责 post 处理大量嵌套聚合结果的人都会很高兴知道目标存储桶路径。您可以通过 aggregation metadata 子句提供它:
POST your-index/_search
{
"aggs": {
"global": {
"global": {},
"meta": {
"accessor_path": "aggs.global.Foo...." <---
},
...
这将 return
{
"aggregations" : {
"global" : {
"meta" : {
"accessor_path" : "aggs.global.Foo..." <---
},
"Foo" : {
2。然后是响应过滤
如果您在同一请求正文中包含多个(子)聚合,则可以通过 filter_path
URI parameter:
减少响应“体积”
POST your-index/_search/template?filter_path=aggregations.global.meta,aggregations.global.*.*.*.*.*.buckets
{
"aggs": {
"global": {
...
这可能真的对你有帮助,也可能没有帮助,因为你的聚合查询看起来很简单而且没有太多子句。
3。最后说一下可维护性
使用可重用查询时,Elasticsearch 提供 Search template API. You'd construct a script containing a parametrized mustache 模板,然后在查询时提供参数。
在您的特定用例中,我建议如下:
- 存储小胡子模板脚本:
POST _scripts/nested_bars_query
{
"script": {
"lang": "mustache",
"source": """
{
"query": {{#toJson}}raw_search_query{{/toJson}},
"aggs": {
"global": {
"global": {},
"meta": {
"accessor_path": "{{accessor_path}}"
},
"aggs": {
"{{notXYZ.agg_name}}": {
"filter": {
"bool": {
"must_not": [
{
"exists": {
"field": "{{notXYZ.field_name}}"
}
}
]
}
},
"aggs": {
"bars": {
"nested": {
"path": "bars"
},
"aggs": {
"{{notValueN.agg_name}}": {
"filter": {
"bool": {
"filter": [
{
"bool": {
"should": {{#toJson}}notValueN.raw_should_clauses{{/toJson}},
"minimum_should_match": 1
}
}
]
}
},
"aggs": {
"bears": {
"nested": {
"path": "bars.bears"
},
"aggs": {
"rules": {
"terms": {
"field": "bars.bears.fruit"
}
}
}
}
}
}
}
}
}
}
}
}
}
}
"""
}
}
- 使用搜索模板 ID (
nested_bars_query
) 定位 /_search/template/
端点。此外,指定上面讨论的 filter_path
和元数据 accessor_path
:
POST your-index-name/_search/template?filter_path=aggregations.global.meta,aggregations.global.*.*.*.*.*.buckets
{
"id": "nested_bars_query",
"params": {
"raw_search_query": {
"match_all": {}
},
"accessor_path": "aggs.global.Foo.bars.notValueN.bears.rules.buckets",
"notXYZ": {
"agg_name": "Foo",
"field_name": "foo"
},
"notValueN": {
"agg_name": "notValueN",
"raw_should_clauses": [
{
"terms": {
"bars.baz": [
"BAZ",
"value2",
"value3"
]
}
},
{
"terms": {
"bars.qux": [
"value4",
"value5",
"value6"
]
}
}
]
}
}
}
您当然可以通过消除定义自定义 agg_name
s 等的可能性来标准化上述内容
以后如果需要引入附加条件,可以修改params
里面的raw_should_clauses
列表。
我的索引中有这样的文档:
{
"foo": null,
"bars": [
{
"baz": "BAZ",
"qux": null,
"bears": [
{
"fruit": "banana"
}
]
}
]
}
我想将 .bars[].bears[].fruit
的唯一值与每个找到的值的计数相加。但是,我也只想计算在 foo
上匹配特定条件的文档的这些深度值,以及在 baz
和 qux
上匹配特定条件的 bars[]
的值。我还想汇总所有文档,忽略搜索查询恰好是什么。
下面的查询完成了我想做的一切:
{
"aggs": {
"global": {
"global": {},
"aggs": {
"notFoo": {
"filter": {
"bool": {
"must_not": [
{
"exists": {
"field": "foo"
}
}
]
}
},
"aggs": {
"bars": {
"nested": {
"path": "bars"
},
"aggs": {
"notValueN": {
"filter": {
"bool": {
"filter": [
{
"bool": {
"should": [
{
"terms": {
"bars.baz": [
"value1",
"value2",
"value3"
]
}
},
{
"terms": {
"bars.qux": [
"value4",
"value5",
"value6"
]
}
}
],
"minimum_should_match": 1
}
}
]
}
},
"aggs": {
"bears": {
"nested": {
"path": "bars.bears"
},
"aggs": {
"rules": {
"terms": {
"field": "bars.bears.fruit"
}
}
}
}
}
}
}
}
}
}
}
}
}
}
此查询有效,但感觉相当庞大和繁重。为了从响应中获得我正在寻找的结果,我必须访问 .aggregations.global.bars.notValueN.bears.fruit.buckets
。有没有办法展平这个大查询?就目前而言,如果以后需要引入任何其他条件,则此查询很难维护。
ES 唯一支持 object key flattening 的地方是集群设置 API。遗憾的是,此策略 不能 用于 API 的其他部分,包括聚合。
不过,还有一些其他技巧值得一提。
1。首先是聚合元数据。
任何负责 post 处理大量嵌套聚合结果的人都会很高兴知道目标存储桶路径。您可以通过 aggregation metadata 子句提供它:
POST your-index/_search
{
"aggs": {
"global": {
"global": {},
"meta": {
"accessor_path": "aggs.global.Foo...." <---
},
...
这将 return
{
"aggregations" : {
"global" : {
"meta" : {
"accessor_path" : "aggs.global.Foo..." <---
},
"Foo" : {
2。然后是响应过滤
如果您在同一请求正文中包含多个(子)聚合,则可以通过 filter_path
URI parameter:
POST your-index/_search/template?filter_path=aggregations.global.meta,aggregations.global.*.*.*.*.*.buckets
{
"aggs": {
"global": {
...
这可能真的对你有帮助,也可能没有帮助,因为你的聚合查询看起来很简单而且没有太多子句。
3。最后说一下可维护性
使用可重用查询时,Elasticsearch 提供 Search template API. You'd construct a script containing a parametrized mustache 模板,然后在查询时提供参数。
在您的特定用例中,我建议如下:
- 存储小胡子模板脚本:
POST _scripts/nested_bars_query
{
"script": {
"lang": "mustache",
"source": """
{
"query": {{#toJson}}raw_search_query{{/toJson}},
"aggs": {
"global": {
"global": {},
"meta": {
"accessor_path": "{{accessor_path}}"
},
"aggs": {
"{{notXYZ.agg_name}}": {
"filter": {
"bool": {
"must_not": [
{
"exists": {
"field": "{{notXYZ.field_name}}"
}
}
]
}
},
"aggs": {
"bars": {
"nested": {
"path": "bars"
},
"aggs": {
"{{notValueN.agg_name}}": {
"filter": {
"bool": {
"filter": [
{
"bool": {
"should": {{#toJson}}notValueN.raw_should_clauses{{/toJson}},
"minimum_should_match": 1
}
}
]
}
},
"aggs": {
"bears": {
"nested": {
"path": "bars.bears"
},
"aggs": {
"rules": {
"terms": {
"field": "bars.bears.fruit"
}
}
}
}
}
}
}
}
}
}
}
}
}
}
"""
}
}
- 使用搜索模板 ID (
nested_bars_query
) 定位/_search/template/
端点。此外,指定上面讨论的filter_path
和元数据accessor_path
:
POST your-index-name/_search/template?filter_path=aggregations.global.meta,aggregations.global.*.*.*.*.*.buckets
{
"id": "nested_bars_query",
"params": {
"raw_search_query": {
"match_all": {}
},
"accessor_path": "aggs.global.Foo.bars.notValueN.bears.rules.buckets",
"notXYZ": {
"agg_name": "Foo",
"field_name": "foo"
},
"notValueN": {
"agg_name": "notValueN",
"raw_should_clauses": [
{
"terms": {
"bars.baz": [
"BAZ",
"value2",
"value3"
]
}
},
{
"terms": {
"bars.qux": [
"value4",
"value5",
"value6"
]
}
}
]
}
}
}
您当然可以通过消除定义自定义 agg_name
s 等的可能性来标准化上述内容
以后如果需要引入附加条件,可以修改params
里面的raw_should_clauses
列表。