我正在尝试对Elasticsearch查询中的聚合结果使用过滤器。基本上,我有数百万个具有以下格式的文档:
{
"useraccountid": 123456,
"purchases_history" : {
"last_updated" : "Sat Apr 27 13:41:46 UTC 2019",
"purchases" : [
{
"purchase_id" : 19854284,
"purchase_date" : "Jan 11, 2017 7:53:35 PM"
},
{
"purchase_id" : 19854285,
"purchase_date" : "Jan 12, 2017 7:53:35 PM"
},
{
"purchase_id" : 19854286,
"purchase_date" : "Jan 13, 2017 7:53:35 PM"
}
]
}
}
首先,我需要做一个SELECT useraccountid, max(purchases_history.purchases.purchase_date) FROM my_index GROUP BY useraccountid
之类的事情,它是使用以下查询完成的,该查询还补充了一个管道过滤器以添加一个HAVING max(purchases_history.purchases.purchase_date) < getdate() - 365
子句,所以我只得到那些文档(即用户帐户)最近一次购买超过一年。
GET my_personal_index/_search
{
"aggs": {
"buckets": {
"composite": {
"size": 1000,
"sources": [
{
"user_account_id": {
"terms": {
"field": "useraccountid"
}
}
}
]
},
"aggs": {
"max_purchase_date": {
"max": {
"field": "purchases_history.purchases.purchase_date"
}
},
"max_purchase_date_filter": {
"bucket_selector": {
"buckets_path": {
"maxPurchaseDate": "max_purchase_date"
},
"script": {
"lang": "painless",
"source": "long now = new Date().getTime(); params.maxPurchaseDate < now - 365"
}
}
}
}
}
}
}
运行此查询时,没有收到任何错误或警告,但结果没有任何意义。我相信是因为执行"long now = new Date().getTime(); params.maxPurchaseDate < now - 365"
时可能正在比较“香蕉和苹果”。因为我实际上不是程序员或技术人员,所以我不知道如何继续绕过并正确地过滤汇总日期。
这是日期容器块的映射:
"purchases_history": {
"properties": {
"purchases": {
"purchase_date": {
"type": "date",
"format": "EEE MMM dd HH:mm:ss z yyyy||MMM d, yyyy HH:mm:ss a"
},
"purchase_id": {
"type": "long"
},
}
}
}
有什么建议吗?谢谢。
答案 0 :(得分:1)
想到的最简单的方法是将脚本更改为
"source": "long now = new Date().getTime(); params.maxPurchaseDate > now - 365*86400000L"
其中每天86400000
的毫秒数。
请注意,根据https://www.elastic.co/guide/en/elasticsearch/painless/master/painless-datetime.html
现在的约会时间
在大多数无痛上下文中,当前日期时间, 现在,不支持。这有两个主要原因。的 首先是脚本通常每个文档运行一次,因此每次 脚本运行不同,现在返回。第二个是脚本 通常以分布式方式运行而没有适当的方式 现在同步。而是使用以下任一方法传递用户定义的参数 字符串日期时间或数字日期时间。数字日期时间是 首选,因为无需进行解析以进行比较。
更新
更多通用脚本:
long nowMillis = new Date().getTime();
Instant instant = Instant.ofEpochMilli(nowMillis);
ZonedDateTime now = ZonedDateTime.ofInstant(instant, ZoneId.of('Z')); // if you need zones
def limit = now.plusDays(-8);
return params.maxPurchaseDate > limit.toInstant().toEpochMilli();
或
Date currentDate = new Date();
Calendar c = Calendar.getInstance();
c.setTime(currentDate);
c.add(Calendar.DATE, -7);
return params.maxPurchaseDate > c.getTimeInMillis();
或其他一些Java解决方案也可以工作
答案 1 :(得分:0)
您尝试过Date Math吗?我用它来过滤索引名称,不确定是否也可以将它用于日期。检查一下:
https://www.elastic.co/guide/en/elasticsearch/reference/current/date-math-index-names.html