ElasticSearch用painless脚本设置文档对象值报错的解决方法
不需要更换脚本语言,Painless完全支持对象类型字段赋值,你写法报错是语法使用错误导致的。
错误根因
Painless是强类型的类Java语法脚本,{}在Painless语法中是代码块分隔符,不是JSON/JS里的对象字面量标识,你直接写ctx._source.myObject={}会被解析为空代码块赋值,直接触发语法/类型推断错误。
ES中存储的object类型字段,在Painless脚本中对应HashMap结构,赋值空对象有两种等效写法:
- 用Painless原生空Map字面量
[:] - 直接实例化HashMap:
new HashMap()
可直接运行的修正后请求
POST myindex/_update_by_query { "script" : { "source": """ ctx._source.categories='categories'; // 空对象赋值,以下两种写法二选一即可 ctx._source.myObject = [:]; // ctx._source.myObject = new HashMap(); """, "lang": "painless" }, "query": { "term" : { "name": "Tony" } } }
扩展场景写法
- 给对象设置带属性的初始值,直接用Painless的Map字面量语法即可,键值对写在方括号中:
// 给myObject赋值{"age":20, "city":"Beijing"}结构 ctx._source.myObject = ['age':20, 'city':'Beijing']; // 给已有对象追加属性用put方法 ctx._source.myObject.put('gender', 'male'); // 嵌套子对象赋值逻辑完全一致 ctx._source.myObject.subObj = [:];
异常排查点
如果改完语法还是报错,先执行以下命令检查字段mapping,确认myObject字段确实是object类型,而非text/keyword/数值等基础类型:
GET myindex/_mapping/field/myObject
高版本Elasticsearch已经废弃了Groovy等其他脚本引擎,Painless是官方唯一默认内置的脚本语言,性能和安全性都最优,完全能满足各类文档更新需求,不需要更换其他脚本实现。
内容的提问来源于stack exchange,提问作者GrinnS
相关产品推荐
相关产品推荐

