当其中一个存储桶路径解析为 'null' 时,ElasticSearch 'bucket_script' 未执行
ElasticSearch 'bucket_script' not executing when one of the bucket paths resolves to 'null'
让我们假设有一个(简化的)索引:
PUT test
{
"mappings": {
"properties": {
"numeric_field_sometimes_empty": {
"type": "integer"
},
"numeric_field_always_present": {
"type": "integer"
}
}
}
}
某些(可能所有已过滤的)文档中可能存在也可能不存在的数字字段:
POST test/_doc
{
"numeric_field_always_present": 10
}
POST test/_doc
{
"numeric_field_always_present": 20
}
我想执行 bucket_script
来计算某些趋势,并且由于 bucket_script
需要成为多桶 agg 的子项,所以我使用 filters
模拟了一个。之后,没有什么能像这样创建我的数字单桶子聚合:
GET test/_search
{
"size": 0,
"aggs": {
"multibucket_simulator": {
"filters": {
"filters": {
"all": {
"match_all": {}
}
}
},
"aggs": {
"avg_empty": {
"avg": {
"field": "numeric_field_sometimes_empty"
}
},
"avg_non_null": {
"avg": {
"field": "numeric_field_always_present"
}
},
"diff": {
"bucket_script": {
"buckets_path": {
"now": "avg_empty.value",
"before": "avg_non_null.value"
},
"script": """
return (params.now != null ? params.now : 0)
- (params.before != null ? params.before : 0)
""",
"format": "###.##"
}
}
}
}
}
}
因为我知道其中一些子聚合的结果可能是 null
(严格的 null
类型,而不是 0
),我检查是否是这种情况三元运算符并继续 return 值差异。这产生:
{
"aggregations":{
"multibucket_simulator":{
"buckets":{
"all":{
"doc_count":2,
"avg_non_null":{
"value":15.0
},
"avg_empty":{
"value":null
}
}
}
}
}
}
完全排除了 diff
存储桶脚本子聚合。这是次优的...
我试过从路径中删除 .value
,这样我就可以直接在脚本中访问和检查 .value
-- 无济于事。
那么问题是——为什么要跳过 null
个存储桶,而且对于这个用例,除了 bucket_script
之外还有其他选择吗?
文档指出
The specified metric must be numeric and the script must return a
numeric value.
我想 null
是否属于该类别是一个讨论的问题。
编辑 1
话虽如此,在每个 avg
agg 上设置一个 missing
参数可以解决这个问题。
编辑 2 和实际答案
这是 gap_policy
. It defaults to skip
and needed to be set to insert_zeros
. Here's the reason。
让我们假设有一个(简化的)索引:
PUT test
{
"mappings": {
"properties": {
"numeric_field_sometimes_empty": {
"type": "integer"
},
"numeric_field_always_present": {
"type": "integer"
}
}
}
}
某些(可能所有已过滤的)文档中可能存在也可能不存在的数字字段:
POST test/_doc
{
"numeric_field_always_present": 10
}
POST test/_doc
{
"numeric_field_always_present": 20
}
我想执行 bucket_script
来计算某些趋势,并且由于 bucket_script
需要成为多桶 agg 的子项,所以我使用 filters
模拟了一个。之后,没有什么能像这样创建我的数字单桶子聚合:
GET test/_search
{
"size": 0,
"aggs": {
"multibucket_simulator": {
"filters": {
"filters": {
"all": {
"match_all": {}
}
}
},
"aggs": {
"avg_empty": {
"avg": {
"field": "numeric_field_sometimes_empty"
}
},
"avg_non_null": {
"avg": {
"field": "numeric_field_always_present"
}
},
"diff": {
"bucket_script": {
"buckets_path": {
"now": "avg_empty.value",
"before": "avg_non_null.value"
},
"script": """
return (params.now != null ? params.now : 0)
- (params.before != null ? params.before : 0)
""",
"format": "###.##"
}
}
}
}
}
}
因为我知道其中一些子聚合的结果可能是 null
(严格的 null
类型,而不是 0
),我检查是否是这种情况三元运算符并继续 return 值差异。这产生:
{
"aggregations":{
"multibucket_simulator":{
"buckets":{
"all":{
"doc_count":2,
"avg_non_null":{
"value":15.0
},
"avg_empty":{
"value":null
}
}
}
}
}
}
完全排除了 diff
存储桶脚本子聚合。这是次优的...
我试过从路径中删除 .value
,这样我就可以直接在脚本中访问和检查 .value
-- 无济于事。
那么问题是——为什么要跳过 null
个存储桶,而且对于这个用例,除了 bucket_script
之外还有其他选择吗?
文档指出
The specified metric must be numeric and the script must return a numeric value.
我想 null
是否属于该类别是一个讨论的问题。
编辑 1
话虽如此,在每个 avg
agg 上设置一个 missing
参数可以解决这个问题。
编辑 2 和实际答案
这是 gap_policy
. It defaults to skip
and needed to be set to insert_zeros
. Here's the reason。