在Elasticsearch中如何用Painless脚本正确获取字段长度?
问题根因
报错栈核心信息dynamic method [java.util.ArrayList, length/0] not found表明:索引中现存的ctx._source.description为数组类型,并非你预期的字符串类型,因此调用字符串专属的长度获取方法会报错。
解决方案
场景1:业务要求description为字符串类型
你需要先兼容现有数组格式的脏数据,同时保证后续写入为标准字符串,修正后的存储脚本如下:
$params = [ 'id' => 'add_new_seller_to_existing_doc', 'body' => [ 'script' => [ 'lang' => 'painless', 'source' => 'if(params.containsKey(\'description\')){ int newDescLen = params.description.length(); if (!ctx._source.containsKey(\'description\')) { ctx._source.description = params.description; } else { int oldDescLen = 0; if (ctx._source.description instanceof List) { // 数组类型取第一个元素长度,如需统计所有元素总长度可遍历累加 oldDescLen = ctx._source.description[0].length(); } else { oldDescLen = ctx._source.description.length(); } if (oldDescLen < newDescLen) { ctx._source.description = params.description; } } }' ] ] ];
你可以同时清洗历史数据,把数组类型的description统一改为字符串,后续就不需要额外做类型判断。批量更新的代码无需修改,替换存储脚本后即可生效。
场景2:业务本身要求description为数组类型
根据你的对比规则调整长度计算逻辑即可:
- 对比两个数组的元素个数:使用
size()方法,判断逻辑改为ctx._source.description.size() < params.description.size() - 对比两个数组内部所有字符串的总长度:遍历数组累加每个元素的长度后再对比。
内容的提问来源于stack exchange,提问作者Catalin
相关产品推荐
相关产品推荐

