1、背景
此篇文档仅仅是简略的记录一下painless
的一些简略的例子,避免当前遗记,不过多波及painless
的语法。
2、筹备数据
2.1 mapping
PUT /index_person{ "mappings": { "properties": { "name": { "type": "keyword" }, "age": { "type": "integer" }, "province": { "type": "keyword" } } }}
2.2 插入数据
PUT /index_person/_bulk{"index":{"_id":1}}{"name":"张三","age":20,"province":"湖北"}{"index":{"_id":2}}{"name":"李四","age":25,"province":"北京"}{"index":{"_id":3}}{"name":"王五","age":30,"province":"湖南"}
3、例子
3.1 (update)更新文档 id=1 的文档,将 age 加 2岁
POST index_person/_update/1{ "script": { "lang": "painless", "source": """ ctx['_source']['age'] += params['incrAge'] """, "params": { "incrAge": 2 } }}
3.2 (update_by_query)如果 province 是北京的话,就将 age 缩小1岁
POST index_person/_update_by_query{ "query": { "term": { "province": { "value": "北京" } } }, "script": { "lang": "painless", "source": """ ctx['_source']['age'] -= params['decrAge'] """, "params": { "decrAge": 1 } }}
3.3 (ctx.op)如果张三的年龄小于20岁就不解决,否则就删除这个文档
POST index_person/_update/1{ "script": { "lang": "painless", "source": """ // 这是默认值,示意的是更新值,从新索引记录 ctx.op = 'index'; if(ctx._source.age < 20){ // 示意不解决 ctx.op = 'none'; }else{ // 示意删除这个文档 ctx.op = 'delete'; } """ }}
3.4 (stored script)如果是湖南省则减少地市字段,值为长沙
3.4.1 创立存储脚本
PUT _scripts/add_city{ "script":{ "lang": "painless", "source": "ctx._source.city = params.city" }}
add_city
为脚本的id
3.4.2 应用存储脚本
POST index_person/_update_by_query{ "query": { "term": { "province": { "value": "湖南" } } }, "script": { "id": "add_city", "params": { "city": "长沙" } }}
3.5 (pipeline)通过pipeline如果插入的文档的age<10则放入到index_person_small索引中
3.5.1 创立pipeline
PUT _ingest/pipeline/pipeline_index_person_small{ "description": "如果插入的文档的age<10则放入到index_person_small索引中", "processors": [ { "script": { "source": """ if(ctx.age < 10){ ctx._index = 'index_person_small'; } """ } } ]}
3.5.2 应用pipeline
PUT index_person/_doc/4?pipeline=pipeline_index_person_small{ "name":"赵六", "age": 8, "province":"四川"}
3.5.3 运行后果
3.6 function_score中应用script_score算分
3.6.1 需要
如果这个用户是湖南
的,则应用 age
作为分数
3.6.2 dsl
GET index_person/_search{ "query": { "function_score": { "query": { "match_all": {} }, "functions": [ { "script_score": { "script": """ if(doc.province.value == 0){ return 0; } if(doc.province.value == '湖南'){ return doc.age.value; } return 0; """ } } ], "boost_mode": "sum", "score_mode": "sum" } }}
3.6.3 运行后果
3.7 script_fields 减少字段
GET index_person/_search{ "query": {"match_all": {}}, "fields": [ "double_age" ], "script_fields": { "double_age": { "script": { "lang": "painless", "source": "doc.age.value * 2" } } }}
3.8 runtime field 减少字段
3.8.1 需要
针对age<25
的文档,返回double_age
字段,否则不解决。
3.8.2 dsl
GET index_person/_search{ "query": { "match_all": {} }, "fields": [ "double_age" ], "runtime_mappings": { "double_age":{ "type": "keyword", "script": """ if(doc.age.size() == 0){ return; } if(doc.age.value < 25){ emit(doc.age.value * 2 + ''); } """ } }}
在runtime field 中,须要应用emit
来返回数据,然而不是emit(null)
3.9 _reindex 中应用
3.9.1 dsl
POST _reindex{ "source": { "index": "index_person" }, "dest": { "index": "index_person_new" }, "script": { "lang": "painless", "source": """ if(ctx._source.age < 25){ ctx._source.tag = '年轻人'; }else{ ctx._source.tag = '中年人'; } """ }}
3.9.2 运行后果
3.10 script query 查问age<25
GET index_person/_search{ "query": { "script": { "script": { "lang": "painless", "source": """ if(doc.age.size() == 0){ return false; } return doc.age.value < 25; """ } } }}
3.11 script 聚合
GET index_person/_search{ "size": 0, "aggs": { "agg_province": { "terms": { "script": { "lang": "painless", "source": """ return doc.province """ }, "size": 10 } }, "agg_age":{ "avg": { "script": "params._source.age" } } }}
4、painless脚本调试
能够通过Debug.explain
来进行一些简略的调试。
5、脚本中的doc[..]和params._source[..]
doc[..]:应用doc关键字,将导致该字段的术语被加载到内存(缓存),这将导致更快的执行,但更多的内存耗费。此外,doc[…]表示法只容许简略的值字段(您不能从中返回json对象),并且仅对非剖析或基于单个术语的字段有意义。然而,如果可能的话,应用doc依然是拜访文档值的举荐办法。
params_source: 每次应用_source都必须加载和解析, 因而应用_source会相对而言要慢点。
![脚本中的doc[..]和params._source[..]](https://img-blog.csdnimg.cn/1...)
6、painless脚本中的上下文
具体理解,请参考这个文档https://www.elastic.co/guide/en/elasticsearch/painless/current/painless-contexts.html