最近在使用es进行如下更新操作时:
POST customer/customer_info/_update_by_query
{
"query": {
"bool": {
"filter": [
{
"term": {
"data_type": {
"value": 1
}
}
},
{
"terms": {
"customer_id": [
"101320130050"
]
}
}
]
}
},
"script": {
"source": """
if(!ctx._source.customer_group.contains(params.val)) {
ctx._source.customer_group.add(params.val)
}""",
"params": {
"val": "22347"
}
}
}
script说明:先查询出data_type是1并且customer_id是101320130050的文档,然后如果这个文档的数组customer_group里不包含22347则把22347加到customer_group里。
运行报错:
dynamic method [java.lang.String,add/1] not fond
后来排查原因是因为customer_group是空或者数组元素是0导致的。简单说就是data_type是1并且customer_id是101320130050的这个文档没有customer_group这个字段,或者customer_group数组里面一个元素也没有导致的,就像是样"customer_group":[ ]
查阅资料发现,es使用script来判断为空和元素等于0可以这样写:
ctx._source.customer_group==null||ctx._source.customer_group?.size() ==0
或者:
ctx._source.customer_group==null||ctx._source.customer_group.length==0
修改后的dsl语句如下:
POST customer_v2023/customer_info/_update_by_query
{
"query": {
"bool": {
"filter": [
{
"term": {
"data_type": {
"boost": 1,
"value": 1
}
}
},
{
"terms": {
"boost": 1,
"customer_id": [
"101320130050"
]
}
}
],
"adjust_pure_negative": true,
"boost": 1
}
},
"script": {
"source": """
if(ctx._source.customer_group==null||ctx._source.customer_group?.size() ==0) {
ctx._source.customer_group=[params.val]
} else if(!ctx._source.customer_group.contains(params.val)) {
ctx._source.customer_group.add(params.val)
}
""",
"params": {
"val": "22347"
}
}
}
script说明: 如果customer_group为空或里面元素为0则将22347直接赋值给customer_group,否则如果customer_group不包含22347则将22347加入到customer_group。
网上其他的如通过doc[‘xxx’].length或doc[‘fieldname’].values.length来判断经过测试没能成功,可能和es的不同版本有关:
"script": {
"source": "doc['xxx'].length==0",
"lang": "painless"
}
关于elasticsearch的script判断字段是否为空以及元素的大小判断参考的其他网址:
elasticsearch filtering by the size of a field that is an array
elasticsearch filter by length of a string field
Script queryedit