关于logstash导入时的Date问题

本文讨论了Elasticsearch在处理日期数据时的格式要求,包括默认的日期格式和多种可能的表示方式。在导入数据时,特别是通过Logstash,可能需要对日期字符串进行转换以符合ES的格式。文中给出了通过Ruby插件调整Logstash输入日期格式的示例,以确保数据能正确导入到Elasticsearch中。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

对于从外部数据源导入到es的日期数据,往往呈现出下列的状态

2015-01-01T12:10:30Z

 

elasticsearch 数据是以 JSON 格式存储的,而 JSON中是并没有 date 数据类型,因此 Elasticsearch 中虽然有 date 类型,但在展示时却要转化成另外的格式。date 类型在 Elasticsearch 展示的格式有下面几种:

1)将日期时间格式化后的字符串,如 "2015-01-01" 或者 "2015/01/01 12:10:30"

2)long 型的整数,意义是 milliseconds-since-the-epoch,翻译一下就是自 1970-01-01 00:00:00 UTC 以来经过的毫秒数。

3)int 型的整数,意义是 seconds-since-the-epoch, 是指自 1970-01-01 00:00:00 UTC 以来经过的秒数。

【注】UTC(Universal Time Coordinated) 叫做世界统一时间,中国大陆和 UTC 的时差是 + 8 ,也就是 UTC+8。不论 date 是什么展示格式,在 Elasticsearch 内部存储时都是转换成 UTC,并且把时区也会计算进去,从而得到 milliseconds-since-the-epoch 并作为存储的格式。

 

在ES中,Date类型的默认格式如下:

"strict_date_optional_time||epoch_millis"

这里的"strict_date_optional_time" 的解释如下:

表示只要是 ISO datetime parser 可以正常解析的都是 strict_date_optional_time。

URL:https://www.joda.org/joda-time/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateOptionalTimeParser--

解释:

dateOptionalTimeParser

public static DateTimeFormatter dateOptionalTimeParser()

Returns a generic ISO datetime parser where the date is mandatory and the time is optional.

The returned formatter can only be used for parsing, printing is unsupported.

This parser can parse zoned datetimes. The parser is strict by default, thus time string 24:00 cannot be parsed.

It accepts formats described by the following syntax:

date-opt-time = date-element ['T' [time-element] [offset]] date-element = std-date-element | ord-date-element | week-date-element std-date-element = yyyy ['-' MM ['-' dd]] ord-date-element = yyyy ['-' DDD] week-date-element = xxxx '-W' ww ['-' e] time-element = HH [minute-element] | [fraction] minute-element = ':' mm [second-element] | [fraction] second-element = ':' ss [fraction] fraction = ('.' | ',') digit+

offset = 'Z' | (('+' | '-') HH [':' mm [':' ss [('.' | ',') SSS]]]) 这里解释一下,日期部分必须指定,其格式可以是:

      • std-date-element
      • ord-date-element
      • week-date-element

而时间部分,如果按照这种格式,必须以字母T来开始:['T' [time-element] [offset]]

而这个时候,如果给ES的Date字段出入如下的值:

"2019-01-01 12:00:01"

的时候,就会报错,这个原因就是,按照确认格式,以上字符串是不能被识别为日期类型

而如下的写法,应该都是合法的写法:

PUT my_index { "mappings": { "properties": { "date": { "type": "date" } } } } PUT my_index/_doc/1 { "date": "2015-01-01" } PUT my_index/_doc/2 { "date": "2015-01-01T12:10:30Z" } PUT my_index/_doc/3 { "date": 1420070400001 } GET my_index/_search { "sort": { "date": "asc"} }

 

那么如何让一个日期型字段支持多种格式呢,答案是:给这个字段指定所有可能的格式(format)

譬如,如下定义:

...

"update_date": {

"type": "date",

"format": "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||strict_date_optional_time||epoch_millis"

},

....

这样定义后,这个update_date字段就可以接受"2019-01-01 12:00:01"这样的字符串作为输入或者查询条件了。

 

而如果对于通过logstash导入ES的日期格式数据,如果输入的日期字符串和上述定义的格式不相匹配是,也可以通过ruby插件尽心编辑,并修改成ES可以接受的格式。示例如下:

 

congfig文件如下:

input {

stdin { }

jdbc {

type => "country_info"

jdbc_connection_string => "jdbc:mysql://127.0.0.1:3306/world"

jdbc_user => "root"

jdbc_password => "root1234"

jdbc_driver_library => "D:/logstash-7.0.1/lib/mysql/mysql-connector-java-5.1.39-bin.jar"

jdbc_driver_class => "com.mysql.jdbc.Driver"

jdbc_default_timezone => "UTC"

jdbc_paging_enabled => "true"

jdbc_page_size => "50000"

statement => "SELECT CODE AS country_code,

NAME,

continent,

region,

SurfaceArea AS surface_area,

indepYear,

population,

LifeExpectancy AS life_expetancy,

gnp,

gnpold,

localname,

governmentform,

headofstate,capital,code2

FROM country"

}

}

filter {

ruby{

path => "D:\logstash-7.0.1\config\handle_country_info.rb"

}

}

output {

stdout { }

elasticsearch {

action => "index"

hosts => "127.0.0.1:9200"

index => "country_info"

document_id => "%{country_code}"

}

}

ruby文件如下:

# the filter method receives an event and must return a list of events.

# Dropping an event means not including it in the return array,

# while creating new ones only requires you to add a new instance of

# LogStash::Event to the returned array

def filter(event)

timestamp = event.get("@timestamp")

update_date = timestamp.time.localtime + 8*60*60

event.set('update_date',update_date.strftime('%Y-%m-%d %H:%M:%S'))

event.remove('@timestamp')

event.remove('@version')

return [event]

end

如上所示,通过ruby程序,可以对日期型字段的值以及格式做灵活调整,这里就是设置成年月日时分秒的格式,加工成了ES可以接受的形式之一。

对于ruby可以做哪些时间类型的运算和处理,请参照ruby的语言说明。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值