我有一些纳入Elasticsearch的每日销售数据。我成功地进行了一些汇总,以找出日期范围内的畅销商品等。

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

  • 确定日期范围内(时段A)的前n位卖家
  • 取得期间A的结果,并计算第二个日期范围(期间B)内这些产品的销售总额
  • 将A期与B期的销售额进行比较,并确定百分比增长超过X%的销售额。

  • 到目前为止,我的尝试:
    {
      "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的结束日期,并且我认为对该范围的结果求和而不是仅对期间A进行求和。我也没有得到%比较,我可能会在应用程序级别执行此比较,但是我知道可以使用脚本化的Elastic查询来处理?

    如果我可以将销售阈值设置为1000次,而不是在A期中获得前n个结果,那将特别棒。

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

    当前正在运行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)将product_id保留在百分比大于5%的位置。

    关于elasticsearch - 弹性汇总以确定期间A与B的百分比增加,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/47453154/

    10-11 08:48