弹性聚合以识别时期 A 与时期 B 百分比增加

Elastic aggregation to identify period A vs B percentage increases

我将一些日常销售数据编入了 Elasticsearch 索引。我成功地 运行 一些聚合来识别日期范围内的畅销书等。

我现在正在尝试编写一个查询来执行以下操作:

我目前的尝试:

{
  "query": {
    "bool": {
      "filter": [
        {
          "range": {
            "date": {
              "gte": "2017-10-01",
              "lte": "2017-10-14"
            }
          }
        }
      ]
    }
  },
  "size": 0,
  "aggs": {
    "data_split": {
      "terms": {
        "size": 10,
        "field": "product_id"
      },
      "aggs": {
        "date_periods": {
          "date_range": {
            "field": "date",
            "format": "YYYY-MM-dd",
            "ranges": [
              {
                "from": "2017-10-01",
                "to": "2017-10-07"
              },
              {
                "from": "2017-10-08",
                "to": "2017-10-14"
              }
            ]
          },
          "aggs": {
            "product_id_split": {
              "terms": {
                "field": "product_id"
              },
              "aggs": {
                "unit_sum": {
                  "sum": {
                    "field": "units"
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}

尽管这会输出两个时间段的结果,但我认为这不是我想要的,因为初始过滤器是从时间段 A 开始日期到时间段 B 结束日期 运行ning 并且我认为求和结果对于该范围而不是仅针对期间 A。我也没有得到百分比比较,我可能会在我的应用程序级别执行此操作,但我知道可以使用脚本化弹性查询来处理吗?

如果不是 A 期的前 n 个结果,我可以设置一个销售阈值,比如 1,000 个销售量,那就太棒了。

任何指点将不胜感激。提前致谢!

当前 运行ning Elastic 5.6

{
  "query": {
    "bool": {
      "filter": [
        {
          "range": {
            "date": {
              "gte": "2017-10-01",
              "lte": "2017-10-14"
            }
          }
        }
      ]
    }
  },
  "size": 0,
  "aggs": {
    "data_split": {
      "terms": {
        "size": 10,
        "field": "product_id"
      },
      "aggs": {
        "date_period1": {
          "filter": {
            "range": {
              "date": {
                "gte": "2017-10-01",
                "lte": "2017-10-07"
              }
            }
          },
          "aggs": {
            "unit_sum": {
              "sum": {
                "field": "units"
              }
            }
          }
        },
        "date_period2": {
          "filter": {
            "range": {
              "date": {
                "gte": "2017-10-08",
                "lte": "2017-10-14"
              }
            }
          },
          "aggs": {
            "unit_sum": {
              "sum": {
                "field": "units"
              }
            }
          }
        },
        "percentage_increase": {
          "bucket_script": {
            "buckets_path": {
              "firstPeriod": "date_period1>unit_sum",
              "secondPeriod": "date_period2>unit_sum"
            },
            "script": "(params.secondPeriod-params.firstPeriod)*100/params.firstPeriod"
          }
        },
        "retain_buckets": {
          "bucket_selector": {
            "buckets_path": {
              "percentage": "percentage_increase"
            },
            "script": "params.percentage > 5"
          }
        }
      }
    }
  }
}

还有一个完整的测试数据在这个gist.

聚合的结果是:

  "aggregations": {
    "data_split": {
      "doc_count_error_upper_bound": 0,
      "sum_other_doc_count": 0,
      "buckets": [
        {
          "key": "A",
          "doc_count": 6,
          "date_period1": {
            "doc_count": 3,
            "unit_sum": {
              "value": 150
            }
          },
          "date_period2": {
            "doc_count": 3,
            "unit_sum": {
              "value": 160
            }
          },
          "percentage_increase": {
            "value": 6.666666666666667
          }
        },
        {
          "key": "C",
          "doc_count": 2,
          "date_period1": {
            "doc_count": 1,
            "unit_sum": {
              "value": 50
            }
          },
          "date_period2": {
            "doc_count": 1,
            "unit_sum": {
              "value": 70
            }
          },
          "percentage_increase": {
            "value": 40
          }
        }
      ]
    }
  }

我们的想法是对两个日期间隔使用两种 filter 类型的聚合。并为每个计算总和。然后,使用 bucket_script 类型的第三个聚合计算百分比增长(但请注意,例如销售额下降,它将是负数)。 然后,使用另一个聚合 - bucket_selector 类型 - 你保留百分比大于 5% 的 product_ids。