首页 新闻 会员 周边

logstash如何增量同步一对多到列表嵌套

0
悬赏园豆:100 [待解决问题]

比如用户表是1,订单表是多,一个用户有多个订单,用左连接查询订单和用户表,持续用步订单,如果order_id不存在则插入,不存在则新增,
select * from order left join user on order.id=user.Id where update_time>update_time order by update_time
{
"user_id": 1,
"name": "Jack",
"order_list": [
{
"order_id": 2,
"good": 3,
"update_time": "2023-06-28 18:22:36"
},
{
"order_id": 3,
"good": 3,
"update_time": "2023-06-28 18:22:36"
}
],
}
{
user_id": 1,
"name": "Jack",
"order_list": [
{
"order_id": 2,
"good": 3,
"update_time": "2023-06-28 18:22:36"
},{
"order_id": 3,
"good": 3,
"update_time": "2023-06-28 18:22:36"
}
]
}

上网查了一下,不知以下的方法能不能持续新增更更新
filter {
aggregate {
task_id => "%{user_id}"
code => "
map['id'] = event.get('user_id')
map['name'] = event.get('name')
map['description'] = event.get('description')
map['update_time'] = event.get('update_time')
map['order_list'] ||=[]
map['order_list'] << {
'order_id' => event.get('order_id'),
'good' => event.get('good'),
}
end
event.cancel()
"
push_previous_map_as_event => true
timeout => 5
}
}

不识少年愁的主页 不识少年愁 | 初学一级 | 园豆:62
提问于:2023-06-28 22:37
< >
分享
所有回答(3)
0

数据量大的表建议不要用left join查询
1.如果order表有clob或blob字段,那么数据量超过10万条就会卡机,例如导出订单数据 exp .../orcl tables='orders',平时需要1分钟,这个情况就要10分钟;
如果没有clob字段,可能超过100万条会卡
2.在这个情况下用left join,那么即使sql加索引也卡
3.后续有需求变更的情况,这个left join可能会增加第三、四个表,会越来越复杂,越来越卡
4.left join的性能在各种数据库的表现是不一样的,同样的语句,可能mssql不卡,但是oralce卡,或者mysql卡,需要针对性的优化,更别说国产达梦等数据库了。
所以建议使用订单的update_time(最后修改时间),作为时间戳,来同步每天的增量数据,即使同步漏了,也可以手工的修改update_time字段达到重新同步的效果。
以下是示例代码,可以加到oracle的job任务中定时执行

CREATE OR REPLACE PROCEDURE order_etl_job IS  
  CURSOR order_cur IS  
    SELECT order_id, order_date, total_amount  
    FROM orders  
    WHERE order_date >= SYSDATE - 1  
    ORDER BY order_date;  
  
  order_rec order_cur%ROWTYPE;  
  
  update_time DATE := SYSDATE;  
BEGIN  
  FOR i IN 1..order_cur.COUNT LOOP  
    FETCH order_cur INTO order_rec;  
  
    -- 检查订单是否存在  
    IF NOT EXISTS (SELECT 1 FROM orders WHERE order_id = order_rec.order_id) THEN  
      INSERT INTO new_orders (order_id, order_date, total_amount, create_time)  
      VALUES (order_rec.order_id, order_rec.order_date, order_rec.total_amount, update_time);  
    ELSE  
      UPDATE existing_orders  
      SET update_time = update_time  
      WHERE order_id = order_rec.order_id;  
    END IF;  
  
    COMMIT;  
  END LOOP;  
END;
lanedm | 园豆:2381 (老鸟四级) | 2023-06-29 09:01
0

根据你提供的信息,你想要使用Logstash实现用户表和订单表的增量同步,并将多个订单嵌套在用户信息中。你已经查阅了一些资料,并尝试使用Logstash的aggregate插件来实现。然而,你对是否能持续新增更更新存在疑问。

根据你提供的代码片段,你的Logstash配置中使用了aggregate插件,并在代码块中定义了聚合逻辑。根据你的需求,这个聚合逻辑应该能够将多个订单信息添加到用户信息的order_list字段中。代码中使用了任务ID %{user_id},并在聚合逻辑中将用户ID、名称等信息放入map中,并将订单信息添加到order_list中。

关于你的疑问,aggregate插件本身是支持持续聚合的。它会根据指定的任务ID来追踪记录,并根据聚合逻辑进行更新。因此,在你的情况下,只要任务ID(即用户ID)保持不变,Logstash将会持续地聚合并将新的订单信息添加到order_list中。

请注意以下几点:

确保你的Logstash配置文件中正确加载了aggregate插件。你可以通过在配置文件的顶部添加filter { aggregate { ... } }来确保正确加载。

根据你的需求,可以适当调整timeout的值。timeout表示任务的超时时间,如果在指定的时间内没有新的事件到达,Logstash将触发聚合并将聚合的结果作为事件输出。你可以根据你的数据量和实际需求来设置合适的超时时间。

在你的配置中,你使用了event.cancel()来取消当前事件的处理。这是因为你希望通过聚合逻辑将多个事件合并为一个。请确保你的聚合逻辑中所有需要的字段都能在第一个事件中获取到,并在最后一个事件触发时将聚合的结果作为输出。

最后,记得测试你的Logstash配置并观察输出是否符合预期。根据你的需求和数据,你可能需要进一步调整聚合逻辑和配置来满足你的实际需求。

Technologyforgood | 园豆:5718 (大侠五级) | 2023-06-29 22:36
0

要将一对多的数据增量同步到列表嵌套中,您可以使用 Logstash 的 jdbc 输入插件和 elasticsearch 输出插件结合使用。下面是一个简单的示例配置:

  1. 首先,您需要在 Logstash 的配置文件中设置 jdbc 输入插件来连接到您的数据库,并执行增量查询。例如,假设您要同步的是一个订单表和一个订单明细表,您可以这样配置:

input {
jdbc {
jdbc_driver_library => "/path/to/your/jdbc/driver.jar"
jdbc_driver_class => "com.mysql.jdbc.Driver"
jdbc_connection_string => "jdbc:mysql://localhost:3306/your_database"
jdbc_user => "your_username"
jdbc_password => "your_password"
schedule => "* * * * *"
statement => "SELECT * FROM orders WHERE updated_at > :sql_last_value"
use_column_value => true
tracking_column => "updated_at"
tracking_column_type => "timestamp"
}
}
上述配置中,我们使用了 jdbc 输入插件连接到数据库,并使用 statement 属性设置增量查询语句。 tracking_column 属性用于指定用于增量同步的列名,这里假设是 updated_at 列。
2. 接下来,您需要使用 elasticsearch 输出插件将数据同步到嵌套列表中。例如,您可以这样配置:

output {
elasticsearch {
hosts => ["localhost:9200"]
index => "your_index"
document_id => "%{id}"
action => "update"
doc_as_upsert => true
scripted_upsert => true
script_lang => "painless"
script => 'if (ctx._source.containsKey("order_details")) { ctx._source.order_details.add(params.event.get("order_detail")) } else { ctx._source.order_details = [params.event.get("order_detail")] }'
}
}
上述配置中,我们使用了 elasticsearch 输出插件将数据同步到 Elasticsearch 中的索引中。 document_id 属性用于指定文档的唯一标识符,这里假设是 id 列。 script 属性用于在更新文档时将数据添加到嵌套列表中。
请根据您的具体数据库和索引结构进行适当的配置和调整。希望这对您有所帮助!如果您有任何其他问题,请随时提问。

jory | 园豆:324 (菜鸟二级) | 2023-07-05 17:37
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册