如何从Elasticsearch Painless _reindex脚本错误信息中定位问题记录?
问题描述
在对大规模索引执行Elasticsearch的_reindex操作时,遇到以下脚本执行错误:
{ "error" : { "root_cause" : [ { "type" : "script_exception", "reason" : "runtime error", "script_stack" : [ "ctx._source.es_resync_time = ctx._source.es_resync_time / 1000000;\n }\n }\n ", " ^---- HERE" ], "script" : " ...", "lang" : "painless", "position" : { "offset" : 1911, "start" : 1871, "end" : 1962 } } ], "type" : "script_exception", "reason" : "runtime error", "script_stack" : [ "ctx._source.es_resync_time = ctx._source.es_resync_time / 1000000;\n }\n }\n ", " ^---- HERE" ], "script" : " ...", "lang" : "painless", "position" : { "offset" : 1911, "start" : 1871, "end" : 1962 }, "caused_by" : { "type" : "class_cast_exception", "reason" : "Cannot apply [/] operation to types [java.lang.String] and [java.lang.Integer]." } }, "status" : 400 }
已知错误原因是es_resync_time字段存在字符串类型值,无法直接与整数做除法。现在需要解决两个问题:
- 能否从当前错误信息中获取问题文档的ID或
es_resync_time的具体值? - 能否在Painless脚本中使用try/catch来处理这类异常,避免整个
_reindex任务中断?
解决方案
1. 获取问题文档的ID和字段值
当前返回的错误信息不包含问题文档的ID或es_resync_time的具体值,Elasticsearch默认不会在这类脚本异常中返回这些上下文信息。要定位具体问题数据,可以通过修改Painless脚本,在执行除法前添加类型判断并输出日志:
// 在除法逻辑前添加判断 if (ctx._source.es_resync_time instanceof String) { // 输出问题文档ID和字段值到Elasticsearch日志 logger.info("异常文档ID: {}, es_resync_time值: {}", ctx._id, ctx._source.es_resync_time); } else { ctx._source.es_resync_time = ctx._source.es_resync_time / 1000000; }
执行修改后的_reindex任务后,你可以在Elasticsearch的日志文件中找到对应的输出,从而定位具体的问题文档。
2. 使用try/catch处理异常
Painless脚本完全支持try/catch块,可以捕获类型转换异常,避免整个_reindex任务因个别错误文档而中断。以下是两种处理思路:
思路1:捕获异常后跳过字段修改
如果不需要强制转换字符串类型的es_resync_time,可以直接跳过修改:
try { ctx._source.es_resync_time = ctx._source.es_resync_time / 1000000; } catch (ClassCastException e) { // 不做任何处理,保留原字段值 }
思路2:尝试转换字符串为数字后再处理
如果需要统一转换该字段,可以在catch块中尝试将字符串转为数值类型,处理失败时再做兜底:
try { ctx._source.es_resync_time = ctx._source.es_resync_time / 1000000; } catch (ClassCastException e) { if (ctx._source.es_resync_time != null) { try { // 将字符串转为长整型后再做除法 ctx._source.es_resync_time = Long.parseLong(ctx._source.es_resync_time) / 1000000; } catch (NumberFormatException ne) { // 处理无法转换为数字的情况,比如设为null或默认值 ctx._source.es_resync_time = null; } } }
内容的提问来源于stack exchange,提问作者Gabriel R.
相关产品推荐
相关产品推荐

