Elasticsearch:painless script 语法基础和实战
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Elasticsearch:painless script 语法基础和实战相关的知识,希望对你有一定的参考价值。
参考技术A摘要: Elasticsearch , Java
script是Elasticsearch的拓展功能,通过定制的表达式实现已经预设好的API无法完成的个性化需求,比如完成以下操作
语法都遵循相同的模式
其中三要素功能如下
使用script脚本修改某文档的某个字段,先插入一条文档
注意在kibiban客户端带上 _update ,否则相当于覆盖整个文档,新建了一个含有script字段的文档。本例中将price字段修改为333,如果是带有单引号的\'333\'则修改为字符串数据,字符串还可以使用 \\转义
获取字段的方式除了使用 ctx._source.字段 之外,还可以 ctx._source[\'字段\']
只要inline脚本中的内容出现些许不一样就需要重新编译,因此推荐的方法是 把inline中固定的部分编译一次,变量命名放在params中传参使用 ,这样只需要编译一次,下次使用调用缓存
这种类似于先注册UDF函数,使用 PUT 对 _scripts 传入脚本
在插入之后使用 GET 可以查看到对应的脚本内容
脚本中并没有指定params,params在调用的是有进行设置,调用的时候使用 id 指定my_script_1这个id即可,不再使用 source
所有update/update_by_query 脚本使用 ctx._source
除了上面快速开始的直接使用=赋值修改的情况,还可以对字段做数值运算,比如加减乘除开方等等
使用 Math.pow 对数值进行开方
Math下的方法还有 sqrt , log 等
主要说明下数组类型字段的更新,使用 ctx._source.字段.add/remove ,先新建一个带有数组字段的文档
使用script将tag数组字段增加元素,使用add
插入新元素后看下数据,已经成功
删除数组元素使用remove指定对应的索引位置即可
如果位数不足会报错类似数组越界
此功能使用search脚本,配合script中的 doc 实现,整体效果类似于map操作,对所选定的文档操作返回
先设置一个字段schema
插入一条日期数据
插入效果如下
下面检索所有文档,提取日期的年份,使用GET+_search请求,DSL中指定script_fields的自定义字段year,给year设置script脚本
doc.dt.value获取第一个数组元素,存储数据类型为 amic getter [org.elasticsearch.script.JodaComp ,该类型通过year属性获得年份。查看以下返回结果,由于没有筛选条件所有文档都被返回,存在dt字段的提取年份,不存在dt字段的也会有返回值为null, 由此可见_search + doc操作实际上是完成了原始文档的一个映射转换操作,并产生了一个自定义的临时字段,不会对原始索引做任何更改操作
如果只返回存在dt字段的,需要在DSL中增加 query 逻辑
插入一个数值数组字段,搜索统计返回数组的和
插入数据
下面计算有goals字段的求goals的和到一个临时字段
在script中每一行结束要加 分号; ,使用Java语法的循环求得数组的和,每个数组元素需要使用Java语法中的Integer.parseInt解析,否则报错String类型无法转Num,查看返回
新建字段和删除字段都是update操作,使用 ctx._source
对于存在dt字段的文档,新增一个字段dt_year,值为dt的年份
以上直接在source中使用ctx._source.dt_year引入一个新列,可惜直接报错
此处并没有向doc一样数据为日期类型而是字符串,因此需要引入Java解析
查看结果
也可以做其他操作比如获得LocalDateTime类型之后再做格式化输出
删除字段直接使用 ctx._source.remove(\\"字段名\\") ,可以删除单个文档,也可以update_by_query批量删除
支持if,else if,else,比如根据某值进行二值判断生成新字段
return用在_search操作中,配合script_fields使用,例如在搜索结果中新增一个字段area为china,此字段不更新到索引只是在搜索时返回
以上指定"_source": true防止被script_fields覆盖,一条输出结果如下
先插入3个子模型分,在生成一个总分,权重是0.6,0.2,0.2
现在计算总分给到score字段
看一下运行结果
直接取ctx._source对应字段进行比较,使用Java三元表达式 ?: 赋值给新字段
有两种情况字段为null和params为null
如果某字段为空,文档不存在该字段,则填充为0
如果传入params不存在某个key,则删除该字段
在本例中使用 String[] cols = new String[3]; 创建了一个静态变量,对于这种集合类的变量painless的语法和Java略有不同,写几个例子如下
List,Map这些集合都没有泛型,并且集合的值貌似不能直接初始化,需要add,put进来
查看某列的值大于某列,在query下可以使用script, 注意格式script下还套着一个script,search请求使用doc获取值
以上语句会报warn,doc选取字段如果字段为空会填充默认值,因此再限制一下字段不为空
以上是关于Elasticsearch:painless script 语法基础和实战的主要内容,如果未能解决你的问题,请参考以下文章
Elasticsearch:Painless scripting 编程实践
Elasticsearch:Painless scripting 编程实践
Elasticsearch Painless script编程
Elasticsearch Painless语言(实现搜索打分基础)