Logstash JDBC同步MongoDB到ES时Kibana仅显示1条记录如何解决
问题根因
所有数据写入ES时被反复覆盖、最终仅保留1条记录,核心原因是配置中元数据字段的读写路径不匹配:
- filter阶段你将MongoDB原始的
_id字段复制到了元数据路径[@metadata][id],随后删除了原始_id字段 - elasticsearch输出阶段,
document_id配置的取值路径为不存在的[@metadata][_id],该路径无有效值时,所有待写入文档会被识别为同一个文档ID,每次写入都会覆盖上一条已存在的文档,最终索引内仅剩下最后同步的1条数据。
修复步骤
- 统一元数据字段的读写路径,二选一即可:
- 方案1:修改filter中的copy目标路径为
[@metadata][_id],和output的取值路径保持一致 - 方案2:修改output中
document_id的取值路径为[@metadata][id],和filter的复制目标保持一致
- 方案1:修改filter中的copy目标路径为
- 建议额外增加
_id值的字符串转换,避免MongoDB的ObjectId类型序列化异常导致ID取值错误 - 修复配置后先删除原有异常的
pritunl索引,再启动Logstash重新同步,避免旧数据干扰结果
修正后可直接使用的配置
input { jdbc { jdbc_driver_class => "mongodb.jdbc.MongoDriver" jdbc_driver_library => "/usr/share/logstash/logstash-core/lib/jars/mongodb_unityjdbc_free.jar" jdbc_user => "" jdbc_password => "" jdbc_connection_string => "jdbc:mongodb://localhost:27017/pritunl" schedule => "* * * * *" jdbc_page_size => 100000 jdbc_paging_enabled => true statement => "select * from servers_output" } } filter { mutate { copy => { "_id" => "[@metadata][doc_id]"} remove_field => ["_id"] } # 统一将ID转为字符串,避免类型兼容问题 mutate { convert => ["[@metadata][doc_id]", "string"] } } output { elasticsearch { hosts => "localhost:9200" index => "pritunl" document_id => "%{[@metadata][doc_id]}" } stdout {} }
补充说明:如果调整后仍出现数据重复/覆盖问题,可以检查JDBC驱动的分页逻辑,部分版本的MongoDB JDBC驱动未指定排序字段时,分页查询会返回重复记录,可在
statement的SQL中增加order by _id强制按主键排序分页。
内容的提问来源于stack exchange,提问作者Maksim Tarasevich
相关产品推荐
相关产品推荐

