当其中一个存储桶路径解析为 '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