Elasticsearch用Painless修改alert字段值出现并发修改异常如何解决
报错原因
抛出concurrent_modification_exception的核心原因是Java集合的快速失败保护机制:Painless底层ctx._source.alert是HashMap结构,你直接遍历它的entrySet()迭代器的过程中,对原HashMap做写入修改操作,迭代器会检测到集合结构发生变化,为了避免不可预期的遍历结果,主动抛出该异常终止运行。
另外原有脚本还存在语法错误:你循环中拿到的alert是Entry对象,不能直接作为Map的key使用,需要调用getKey()方法获取字段名才能正确赋值。
修复后的脚本
我们先把alert对象的所有key复制到一个独立的ArrayList中,遍历这个和原Map没有关联的列表,就不会触发并发修改校验。同时额外增加了字符串类型判断,避免alert下存在非字符串类型字段时,调用length()方法抛出类型错误,完整脚本如下:
{ "script": { "lang": "painless", "source": """ // 复制所有key到独立列表,避免遍历过程中修改原map触发异常 def alertKeys = new ArrayList(ctx._source.alert.keySet()); for (key in alertKeys) { def value = ctx._source.alert[key]; // 仅对字符串类型的字段做长度校验和截断替换 if (value instanceof String && value.length() > params.number_of_characters) { ctx._source.alert[key] = "value was truncated since it was too long"; } } """, "params": { "number_of_characters": 5 } } }
内容的提问来源于stack exchange,提问作者Dennis
相关产品推荐
相关产品推荐

