Elasticsearch Painless脚本如何正确使用Arrays.binarySearch方法
编译报错及功能不符合预期的核心原因
- 基础语法错误:判断语句末尾多写了1个右括号,
> 0))处存在冗余括号,直接触发编译阶段解析失败 - 类未导入:Painless 不会自动加载
java.util.Arrays类,直接写Arrays.binarySearch会因找不到类触发编译错误 - 判断逻辑错误:
Arrays.binarySearch方法匹配到目标值时,返回值是大于等于0的数组下标(下标从0开始计数),仅判断>0会漏掉下标为0的匹配项;未匹配到时才会返回负数 - 性能隐患:直接把长度25万的数组硬编码拼接进脚本源码的写法,会导致每次请求都触发脚本重新编译,不仅传输开销大,还极易触发 Elasticsearch 的脚本编译限流阈值,生产环境完全不可用
正确实现方式
临时测试修正版
如果只是做小规模功能验证,修正语法、类名、判断逻辑即可,Arrays需要写全限定类名:
my_script = f""" if (java.util.Arrays.binarySearch({sorted_keys}, doc['_meta.key'].value) >= 0) return 0; return 1; """ script = {"script": {"lang": "painless", "source": my_script }}
也可以在脚本开头显式导入类后再简写:
import java.util.Arrays; // 后续直接调用Arrays.binarySearch即可
生产环境推荐写法
将大数组作为脚本参数传递,而非拼接在源码中,脚本仅需编译一次即可被所有请求复用缓存,性能提升非常明显:
my_script = """ if (java.util.Arrays.binarySearch(params.sorted_keys, doc['_meta.key'].value) >= 0) return 0; return 1; """ script = { "script": { "lang": "painless", "source": my_script, "params": { "sorted_keys": sorted_keys } } }
注意:传入的
sorted_keys必须是严格按自然顺序升序排列的数组,否则二分查找的结果不可预期,该规则和Java原生Arrays.binarySearch的要求完全一致。
内容的提问来源于stack exchange,提问作者Naim Mustafa
相关产品推荐
相关产品推荐

