Elasticsearch Painless获取当前时间
Elasticsearch Painless获取当前时间本文讨论下Elasticsearch如何获取当前时间,通常需要计算时间间隔时使用。日期处理Painless使用标准的Java库,主要类有:java.timejava.time.chronojava.time.formatjava.time.temporaljava.time.zone官方API地址为:https://www....
Elasticsearch Painless获取当前时间
本文讨论下Elasticsearch如何获取当前时间,通常需要计算时间间隔时使用。日期处理Painless使用标准的Java库,主要类有:
- java.time
- java.time.chrono
- java.time.format
- java.time.temporal
- java.time.zone
官方API地址为:https://www.elastic.co/guide/en/elasticsearch/painless/master/painless-api-reference-shared-org-elasticsearch-script.html#painless-api-reference-shared-JodaCompatibleZonedDateTime
1. Java 8 获取当前时间
我们首先介绍几种Java 8获取当前日期、时间方式。
1.1. 当前Date
使用java.time.LocalDate 获取当前系统日期:
LocalDate localDate = LocalDate.now();
获取带时区的当前日期:
LocalDate localDate = LocalDate.now(ZoneId.of("GMT+02:30"));
ZonedDateTime zbj = ZonedDateTime.now(ZoneId.of("Asia/Shanghai"));
当然也可以通过LocalDateTime获得LocalDate:
LocalDateTime localDateTime = LocalDateTime.now();
LocalDate localDate = localDateTime.toLocalDate();
1.1. 当前Time
通过LocalTime类获取当前时间:
LocalTime localTime = LocalTime.now();
指定时区获取:
LocalTime localTime = LocalTime.now(ZoneId.of("GMT+02:30"));
ZonedDateTime zbj = ZonedDateTime.now(ZoneId.of("Asia/Shanghai"));
也可以通过LocalDateTime类获取LocalTime:
LocalDateTime localDateTime = LocalDateTime.now();
LocalTime localTime = localDateTime.toLocalTime();
1.3. 当前Timestamp
java.time.Instant 从epoch时间获取时间戳,即从1970-01-01T00:00:00Z开始计算毫秒正数值:
Instant instant = Instant.now();
long timeStampMillis = instant.toEpochMilli();
当然也可以获取秒数:
Instant instant = Instant.now();
long timeStampSeconds = instant.getEpochSecond();
2. Elasticsearch Painless获取当前时间
在大多数Painless上下文中,当前datetime,now都不支持。主要有两个原因,第一是脚本对每个文档都运行一次,导致每次now的返回值不同。第二脚本通常运行在分布式环境,无法获得一致的now。一般采用的方法是用户定义参数,字符串类型或数值类型的日期,数值类型更好,无需进行格式解析。
举例:
long now = params['now'];
ZonedDateTime zdt =ZonedDateTime.ofInstant(doc['event_datetime'].value.toInstant(), ZoneId.of('Z'))
long millisDateTime = zdt.toInstant().toEpochMilli();
long elapsedTime = now - millisDateTime;
我们看到官网示例直接写ZonedDateTime zdt = doc[‘event_datetime’];,这样会报异常:即JodaCompatibleZonedDateTime类型不能转为ZonedDateTime 。
2.1 计算日期间隔示例
定义映射
PUT /messages
{
"mappings": {
"properties": {
"priority": {
"type": "integer"
},
"datetime": {
"type": "date"
},
"message": {
"type": "text"
}
}
}
}
载入示例数据
POST /_bulk
{ "index" : { "_index" : "messages", "_id" : "1" } }
{ "priority": 1, "datetime": "2019-07-17T12:13:14Z", "message": "m1" }
{ "index" : { "_index" : "messages", "_id" : "2" } }
{ "priority": 1, "datetime": "2019-07-24T01:14:59Z", "message": "m2" }
{ "index" : { "_index" : "messages", "_id" : "3" } }
{ "priority": 2, "datetime": "1983-10-14T00:36:42Z", "message": "m3" }
{ "index" : { "_index" : "messages", "_id" : "4" } }
{ "priority": 3, "datetime": "1983-10-10T02:15:15Z", "message": "m4" }
{ "index" : { "_index" : "messages", "_id" : "5" } }
{ "priority": 3, "datetime": "1983-10-10T17:18:19Z", "message": "m5" }
{ "index" : { "_index" : "messages", "_id" : "6" } }
{ "priority": 1, "datetime": "2019-08-03T17:19:31Z", "message": "m6" }
{ "index" : { "_index" : "messages", "_id" : "7" } }
{ "priority": 3, "datetime": "2019-08-04T17:20:00Z", "message": "m7" }
{ "index" : { "_index" : "messages", "_id" : "8" } }
{ "priority": 2, "datetime": "2019-08-04T18:01:01Z", "message": "m8" }
{ "index" : { "_index" : "messages", "_id" : "9" } }
{ "priority": 3, "datetime": "1983-10-10T19:00:45Z", "message": "m9" }
{ "index" : { "_index" : "messages", "_id" : "10" } }
{ "priority": 2, "datetime": "2019-07-23T23:39:54Z", "message": "m10" }
统计星期
GET /messages/_search?pretty=true
{
"size": 0,
"aggs": {
"day-of-week-count": {
"terms": {
"script": "return doc[\"datetime\"].value.getDayOfWeekEnum();"
}
}
}
}
返回结果如下:
...
"aggregations" : {
"day-of-week-count" : {
"doc_count_error_upper_bound" : 0,
"sum_other_doc_count" : 0,
"buckets" : [
{
"key" : "MONDAY",
"doc_count" : 3
},
{
"key" : "SUNDAY",
"doc_count" : 2
},
{
"key" : "WEDNESDAY",
"doc_count" : 2
},
{
"key" : "FRIDAY",
"doc_count" : 1
},
{
"key" : "SATURDAY",
"doc_count" : 1
},
{
"key" : "TUESDAY",
"doc_count" : 1
}
]
}
}
统计上午和下午
GET /messages/_search?pretty=true
{
"size": 0,
"aggs": {
"am-pm-count": {
"terms": {
"script": "return doc[\"datetime\"].value.getHour() < 12 ? \"AM\" : \"PM\";"
}
}
}
}
返回响应:
"aggregations" : {
"am-pm-count" : {
"doc_count_error_upper_bound" : 0,
"sum_other_doc_count" : 0,
"buckets" : [
{
"key" : "PM",
"doc_count" : 7
},
{
"key" : "AM",
"doc_count" : 3
}
]
}
}
统计年
GET /messages/_search?pretty=true
{
"size": 3,
"script_fields" : {
"message_age" : {
"script" : {
"source": "ZonedDateTime now = ZonedDateTime.ofInstant(Instant.ofEpochMilli(params['now']), ZoneId.of('Z')); ZonedDateTime mdt=ZonedDateTime.ofInstant(doc['datetime'].value.toInstant(), ZoneId.of('Z'));return mdt.until(now, ChronoUnit.YEARS);",
"params": {
"now": 1674005645830
}
}
}
}
}
可读形式脚本:
ZonedDateTime now = ZonedDateTime.ofInstant(Instant.ofEpochMilli(params['now']), ZoneId.of('Z'));
ZonedDateTime mdt=ZonedDateTime.ofInstant(doc['datetime'].value.toInstant(), ZoneId.of('Z'));
return mdt.until(now, ChronoUnit.YEARS);
第一步获取ZonedDateTime类型now对象。然后转换文档的datetime字段为ZonedDateTime mdt对象,最后 mdt.until(now, ChronoUnit.YEARS)求两个时间间隔年份。
这里需要注意的是doc[‘datetime’].value类型为JodaCompatibleZonedDateTime,需要通过ZonedDateTime.ofInstant(doc['datetime'].value.toInstant(), ZoneId.of('Z'))
转换为ZonedDateTime。
响应如下:
"hits" : [
{
"_index" : "messages",
"_type" : "_doc",
"_id" : "1",
"_score" : 1.0,
"fields" : {
"message_age" : [
3
]
}
},
{
"_index" : "messages",
"_type" : "_doc",
"_id" : "2",
"_score" : 1.0,
"fields" : {
"message_age" : [
3
]
}
},
{
"_index" : "messages",
"_type" : "_doc",
"_id" : "3",
"_score" : 1.0,
"fields" : {
"message_age" : [
39
]
}
}
]
3. 总结
本文介绍Painless如何获取当前时间,并计算时间间隔。
更多推荐
所有评论(0)