本文使用的elk版本均为7.17.3
需求
logstash定时根据id更新es数据,数据库中有a_time,b_time,c_time三个动态时间分别在三个表中,现需要根据这三个表更新es中这三个对应字段,且同时维护last_time字段;要求last_time为这a_time,b_time,c_time中的最大值。
es索引字段如下
{
"id" : {
"type" : "long"
},
"a_time" : {
"type" : "date"
},
"b_time" : {
"type" : "date"
},
"c_time" : {
"type" : "date"
},
"last_time" : {
"type" : "date"
}
}
思路
通过es的script脚本在更新时动态生成last_time的值
实现
这三张表无法通过一个关联关系来一下查出a_time,b_time,c_time的值,因此logstsh需要配置多个条线。
pipelines.yml的配置如下
# a时间更新
- pipeline.id: a_time
pipeline.workers: 2
pipeline.batch.size: 2000
queue.type: persisted
path.config: "/usr/share/logstash/config/a_time.conf"
# b时间更新
- pipeline.id: b_time
pipeline.workers: 2
pipeline.batch.size: 2000
queue.type: persisted
path.config: "/usr/share/logstash/config/b_time.conf"
# c时间更新
- pipeline.id: c_time
pipeline.workers: 2
pipeline.batch.size: 2000
queue.type: persisted
path.config: "/usr/share/logstash/config/c_time.conf"
pipeline的配置文件如下:
a_time.conf配置如下:
input {
stdin {
}
jdbc {
# 数据库连接
jdbc_connection_string => "jdbc:oracle:thin:@127.0.0.1:1521/test"
# 用户名密码
jdbc_user => "test"
jdbc_password => "test"
# 驱动jar包的位置
jdbc_driver_library => "/你自己的路径/ojdbc8-21.5.0.0.jar"
#oracle的Driver
jdbc_driver_class => "Java::oracle.jdbc.driver.OracleDriver"
jdbc_paging_enabled => "true"
#处理中文乱码
codec => plain { charset => "UTF-8"}
jdbc_page_size => "50000"
statement => "select * from(select qb.a_time,eb.id from (select max(a_time) a_time,doc_id from a_info where DELETE_FLG = 0 group by doc_id )qb left join BASE_INFO eb on qb.doc_id = eb.doc_id ) where id is not null"
#cron表达式 每天一点整更新
schedule => "0 1 * * *"
clean_run => false
}
}
filter{
mutate{
remove_field => ["@version"]
remove_field => ["@timestamp"]
}
}
output {
elasticsearch {
hosts => "http://127.0.0.1:9200/"
user =>"elastic"
password =>"123456"
# index名
index => "test_index"
#update表示通过 id 更新文档
action => "update"
# 需要关联的数据库中有有一个id字段,对应索引的id号
document_id => "%{id}"
# 脚本判断a_time,b_time,c_time更新时间最大值,并赋值给last_time
#params.event.get('a_time')获取的是当前目标修改的a_time
#ctx._source.a_time获取的是es目标索引中存储的a_time的值
script => "
List res = new ArrayList();
if(params.event.get('a_time')!=null){
res.add(params.event.get('a_time'))
}
if(ctx._source.b_time!=null){
res.add(ctx._source.b_time)
}
if(ctx._source.c_time!=null){
res.add(ctx._source.c_time)
}
ctx._source.last_time = Collections.max(res);
ctx._source.a_time = params.event.get('a_time');
"
}
}
script中编写脚本可以直接使用jdk自带的api(是否全都可用不清楚),也可以直接new 对象很方便。
参考文档
1:logstash-plugins-outputs-elasticsearch
2:es脚本语言painless-lang-spec