使用Logstash同步SQL数据到Elasticsearch时遇document_parsing_exception错误
Logstash JDBC导入Elasticsearch嵌套映射解析失败解决方法
问题背景
用Logstash的JDBC输入插件把SQL数据库数据索引到Elasticsearch,需要解析JSON格式字段,且已为该字段配置嵌套(nested)映射,但始终触发document_parsing_exception错误。移除自定义映射后数据能正常导入,但业务要求必须保留嵌套映射。
错误信息
"error"=>{"type"=>"document_parsing_exception", "reason"=>"[1:93] object mapping for [myfield] tried to parse field [myfield] as object, but found a concrete value"}}}}
配置详情
Elasticsearch嵌套映射
"myfield": { "type": "nested", "properties": { "lang": { "type": "text" }, "text": { "type": "text" } } }
数据库对应字段内容
[{"lang": "fr", "text": "text example"}]
已尝试的无效方法
- Ruby脚本解析(因涉及多字段选择此方式),未解决问题
- JSON过滤器解析,同样无效
- 不添加任何解析过滤器,错误依然存在
尝试过的Ruby脚本
json_fields = [ "myfield", [...] ] json_fields.each do |field| if valid?(event.get(field)) parsed_field = JSON.parse(event.get(field)) if (parsed_field.is_a?(Hash) || parsed_field.is_a?(Array)) event.set(field, parsed_field) else event.remove(field) end else event.remove(field) end end
尝试过的JSON过滤器
json{ source => "cdm_cours_7_7_rhythm" target => "cdm_cours_7_7_rhythm" }
问题根因
Elasticsearch的嵌套(nested)类型要求字段值是对象数组,但Logstash向ES发送的数据中,myfield仍为字符串类型(未被正确解析为JSON数组),ES无法将字符串解析为嵌套对象,因此抛出错误。
常见触发点:
- JDBC输入插件直接将数据库中的JSON字符串原样读取,未自动解析
- 解析脚本/过滤器存在字段名不匹配、异常未处理等问题,导致解析失败
- 解析后的数据类型不符合嵌套映射要求(比如解析成单个对象而非数组)
解决步骤
1. 修正字段匹配问题(针对JSON过滤器)
你提供的JSON过滤器中,source和target字段写的是cdm_cours_7_7_rhythm,但实际需要解析的字段是myfield,字段名不匹配导致解析完全没生效。修正后的JSON过滤器配置:
json { source => "myfield" target => "myfield" # 遇到无效JSON时跳过,避免阻断整个事件 skip_on_invalid_json => true # 解析失败时设置空数组,符合嵌套类型要求 add_field => { "[myfield]" => "[]" } remove_field => "[myfield]" }
2. 修正Ruby脚本的逻辑漏洞
原脚本的valid?方法未明确定义,且缺乏JSON解析异常捕获,容易导致解析失败后字段仍为字符串。修正后的脚本:
json_fields = ["myfield"] json_fields.each do |field| value = event.get(field) # 仅处理非空的字符串类型字段 if value && value.is_a?(String) && !value.strip.empty? begin parsed_field = JSON.parse(value) # 验证解析结果是对象数组(符合嵌套映射要求) if parsed_field.is_a?(Array) && parsed_field.all? { |item| item.is_a?(Hash) } event.set(field, parsed_field) else # 不符合要求时设置空数组,避免触发ES错误 event.set(field, []) end rescue JSON::ParserError => e # 解析失败时设置空数组,同时打印错误日志 event.set(field, []) puts "解析字段#{field}失败: #{e.message}" end else # 字段为空或不存在时,设置空数组 event.set(field, []) end end
3. 验证解析结果
在Logstash的output配置中添加标准输出,确认myfield已被解析为数组类型:
output { elasticsearch { hosts => ["your-es-host:9200"] index => "your-index" } stdout { codec => rubydebug } }
正常解析后的输出应该类似:
"myfield" => [ [0] { "lang" => "fr", "text" => "text example" } ]
只要myfield是对象数组的形式,就能符合Elasticsearch嵌套映射的要求,不会再触发解析错误。
内容的提问来源于stack exchange,提问作者Damidas
相关产品推荐
相关产品推荐

