Elasticsearch报错:dynamic method [java.util.HashMap, add/1] not found 求助
解决Elasticsearch _update_by_query中HashMap add方法报错的问题
错误原因分析
从你提供的示例数据和报错信息来看,问题很明确:你试图给一个HashMap类型的字段调用add()方法,但HashMap并没有这个方法。
看Arvind的文档数据:
{ "_source" : { "EmpUserID" : 106, "Address" : { "AddressNumber" : 201, "AddressID" : 200 }, "Gender" : "Male", "EmpName" : "Arvind", "Age" : 30 } }
这里的Address是一个单个对象(对应Java里的HashMap),而不是数组(List)。你的脚本里用ctx._source.Address.add(params.tag),相当于给HashMap调用List的add()方法,自然会抛出dynamic method [java.util.HashMap, add/1] not found的错误。
解决方案(分两种场景)
场景1:需要将Address改为数组,存储多个地址
如果你想让Arvind的Address变成数组,以后可以添加多个地址,需要先把现有的单个Address对象转成数组,再添加新元素。修改后的查询脚本如下:
POST employees-details/_update_by_query { "query": { "match": { "EmpName": "Arvind" } }, "script": { "source": """ // 检查Address是否为数组,不是的话先转成数组 if (!(ctx._source.Address instanceof List)) { ctx._source.Address = [ctx._source.Address]; } // 添加新的地址对象到数组中 ctx._source.Address.add(params.tag); """, "lang": "painless", "params": { "tag":{ "AddressID":144, "AddressNumber":458 } } } }
执行后,Arvind的Address会变成:
"Address": [ { "AddressNumber": 201, "AddressID": 200 }, { "AddressID":144, "AddressNumber":458 } ]
场景2:只是替换现有的单个Address对象
如果你不需要存储多个地址,只是想替换掉当前的Address,直接赋值即可,脚本更简单:
POST employees-details/_update_by_query { "query": { "match": { "EmpName": "Arvind" } }, "script": { "source": "ctx._source.Address = params.tag", "lang": "painless", "params": { "tag":{ "AddressID":144, "AddressNumber":458 } } } }
后续优化建议
为了避免以后再出现类似类型不匹配的问题,建议你修改索引的mapping:
- 如果要存储多个地址,把
Address设为nested类型(支持对数组内的单个对象进行查询)或者object类型(数组形式但不支持独立查询内部元素) - 如果只存单个地址,保持
object类型即可
修改mapping的示例(以nested类型为例):
PUT employees-details/_mapping { "properties": { "Address": { "type": "nested", "properties": { "AddressID": {"type": "integer"}, "AddressNumber": {"type": "integer"} } } } }
内容的提问来源于stack exchange,提问作者M_x
相关产品推荐
相关产品推荐

