我有一些纳入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的结束日期,并且我认为对该范围的结果求和而不是仅对期间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/