首页 > 解决方案 > 来自存储桶和更高级别聚合的弹性脚本

问题描述

我想将指标的每日平均值(文本中出现的单词频率)与特定日期的值进行比较。这是在一周内。我的目标是检查是否有尖峰。如果最后一天远高于每日平均水平,我会触发警报。

因此,根据我在 Elasticsearch 中的输入,我计算了一周中的每日平均值,并找出了该周最后一天的值。

为了获得一周的每日平均值,我只是使用字段range查询来减少一周的数据,所以我所有的可用数据都是给定的一周。我计算总和并除以 7 作为每日平均值。date

为了获得最后一天的值,我按照另一个问题(如何在 Elasticsearch 中的 date_histogram 选择器中选择最后一个桶)中的date建议,对字段进行了术语聚合,降序排列和大小为 1

整个输出如下。在这里,您可以看到单词“rama0”和“rama1”及其对应的频率。

{
  "aggregations" : {
    "the_keywords" : {
      "doc_count_error_upper_bound" : 0,
      "sum_other_doc_count" : 0,
      "buckets" : [
        {
          "key" : "rama0",
          "doc_count" : 4200,
          "the_last_day" : {
            "doc_count_error_upper_bound" : 0,
            "sum_other_doc_count" : 3600,
            "buckets" : [
              {
                "key" : 1580169600000,
                "key_as_string" : "2020-01-28T00:00:00.000Z",
                "doc_count" : 600,
                "the_last_day_frequency" : {
                  "value" : 3000.0
                }
              }
            ]
          },
          "the_weekly_sum" : {
            "value" : 21000.0
          },
          "the_daily_average" : {
            "value" : 3000.0
          }
        },
        {
          "key" : "rama1",
          "doc_count" : 4200,
          "the_last_day" : {
            "doc_count_error_upper_bound" : 0,
            "sum_other_doc_count" : 3600,
            "buckets" : [
              {
                "key" : 1580169600000,
                "key_as_string" : "2020-01-28T00:00:00.000Z",
                "doc_count" : 600,
                "the_last_day_frequency" : {
                  "value" : 3000.0
                }
              }
            ]
          },
          "the_weekly_sum" : {
            "value" : 21000.0
          },
          "the_daily_average" : {
            "value" : 3000.0
          }
        },
        [...]
      ]
    }
  }
}

现在我已经the_daily_average在一个高层次的输出中,并且在聚合the_last_day_frequency中的单元素buckets列表中。the_last_day我不能使用 abucket_script来比较它们,因为我不能引用单个存储桶(如果我将脚本放在the_last_day聚合之外),如果我将脚本放在里面,我也不能引用更高级别的聚合the_last_day

IMO 合理的做法是将脚本放在聚合之外并使用docs中提到buckets_path的语法使用 a ,但我已经尝试过和变体(首先硬编码直到它工作),但我无法参考一个特定的桶。<AGG_NAME><MULTIBUCKET_KEY>"var1": "the_last_day[1580169600000]>the_last_day_frequency"

我的最终目标是列出最后一天频率大大超过每日平均值的关键字。

对于任何有兴趣的人,我目前的查询如下。请注意,我正在努力解决的部分已被注释掉。

body='{
    "query": {
        "range": {
            "date": {
                "gte": "START",
                "lte": "END"
            }
        }
    },
    "aggs": {
        "the_keywords": {
            "terms": {
                "field": "keyword",
                "size": 100
            },
            "aggs": {
                "the_weekly_sum": {
                    "sum": {
                        "field": "frequency"
                    }
                },
                "the_daily_average" : {
                    "bucket_script": {
                        "buckets_path": {
                            "weekly_sum": "the_weekly_sum"
                        },
                        "script": {
                            "inline": "return params.weekly_sum / 7"
                        }
                    }
                },
                "the_last_day": {
                    "terms": {
                        "field": "date",
                        "size": 1,
                        "order": {"_key": "desc"}
                    },
                    "aggs": {
                        "the_last_day_frequency": {
                            "sum": {
                                "field": "frequency"
                            }
                        }
                    }
                }/*,
                "the_spike": {
                    "bucket_script": {
                        "buckets_path": {
                            "last_day_frequency": "the_last_day>the_last_day_frequency",
                            "daily_average": "the_daily_average"
                        },
                        "script": {
                            "inline": "return last_day_frequency / daily_average"
                        }
                    }
                }*/
            }
        }
    }
}'

标签: elasticsearch

解决方案


在您的查询 the_last_day>the_last_day_frequency 指向一个存储桶而不是单个值,因此它会引发错误。您需要从“the_last_day_frequency”中获取单个指标值,您可以使用max_bucket来实现。然后您可以使用bucket_Selector 聚合将最后一天的值与平均值进行比较

询问:

"aggs": {
    "the_keywords": {
      "terms": {
        "field": "keyword",
        "size": 100
      },
      "aggs": {
        "the_weekly_sum": {
          "sum": {
            "field": "frequency"
          }
        },
        "the_daily_average": {
          "bucket_script": {
            "buckets_path": {
              "weekly_sum": "the_weekly_sum"
            },
            "script": {
              "inline": "return params.weekly_sum / 7"
            }
          }
        },
        "the_last_day": {
          "terms": {
            "field": "date",
            "size": 1,
            "order": {
              "_key": "desc"
            }
          },
          "aggs": {
            "the_last_day_frequency": {
              "sum": {
                "field": "frequency"
              }
            }
          }
        },
        "max_frequency_last_day": {
          "max_bucket": {
            "buckets_path": "the_last_day>the_last_day_frequency"
          }
        },
        "the_spike": {
          "bucket_selector": {
            "buckets_path": {
              "last_day_frequency": "max_frequency_last_day",
              "daily_average": "the_daily_average"
            },
            "script": {
              "inline": "params.last_day_frequency > params.daily_average"
            }
          }
        }
      }
    }
  }
````


推荐阅读