项目场景:
需要将现有列表查询数据源由ORACLE替换为ES,相应SQL转换为ES的DSL语句。
问题描述
SQL IN :QueryBuilders.termsQuery() 时异常。
[terms] unknown token [END_ARRAY] after [XXX]
List<String> list = new ArrayList<>();
SearchSourceBuilder dsl = new SearchSourceBuilder();
dsl.query(QueryBuilders.termsQuery("xxx", StringUtils.isEmpty(list) ? "" : list));
原因分析:
查看源码发现QueryBuilders.termsQuery有很多重载方法
public static TermsQueryBuilder termsQuery(String name, Object... values) {
return new TermsQueryBuilder(name, values);
}
public static TermsQueryBuilder termsQuery(String name, Collection<?> values) {
return new TermsQueryBuilder(name, values);
}
使用三目表达式返回结果类型不同,统一走Object类型的重载方法,查看其源码发现对入参直接包装 成了List。相当于在原有list基础上又包装了一层,导致问题出现。
public TermsQueryBuilder(String fieldName, Object... values) {
this(fieldName, values != null ? Arrays.asList(values) : (Iterable<?>) null);
}
}
DSL语句对比
异常情况:{
"terms" : {
"xxx" : [
[
"asd"
]
],
"boost" : 1.0
}
想要的结果:
{
"terms" : {
"xxx" : [
"asd"
],
"boost" : 1.0
}
}
解决方案:
本就该对参数在外层进行判空,脑子抽了写在里面了。
if (StringUtils.isNotEmpty(list)){
//这么写底层走的是 Collection类型的重载方法
QueryBuilders.termsQuery("xxx", list);
...
}
备注:QueryBuilders.termsQuery()若查询参数为多个时,最好确保参数类型保持一致,让ES走正确的重载方法。使用三目表达式作为参数,最好确保参数类型也一直否则会走 Object类型的重载方法。