1. 借鑒
極客時(shí)間 阮一鳴老師的Elasticsearch核心技術(shù)與實(shí)戰(zhàn)
官網(wǎng) modules-scripting-using
官網(wǎng) painless-execute-api
官網(wǎng) Painless Scripting Language
Elasticsearch Painless script編程
2. 開(kāi)始
script在很多場(chǎng)景下都有使用到,我們這次來(lái)看下
結(jié)構(gòu)
"script": {
"lang": "painless" // 腳本語(yǔ)言:painless(默認(rèn)),expression,可省略
"source": """ // 腳本內(nèi)容(inline腳本)
這里面是腳本
""",
"id": "" // 腳本的ID(stored腳本),source和ID只能存在一個(gè)
"params": { // source里面需要的參數(shù)
"key1": value1,
"key2": value2
}
}
注意:本篇文章所有腳本,lang為painless
上下文
在不同的上下文中,獲取文檔字段使用的語(yǔ)法是不同的。
| 上下文 | 語(yǔ)法 | 示例:獲取文檔中的name屬性 |
|---|---|---|
| pipeline | ctx.field_name | ctx.name |
| update | ctx._source.field_name | ctx._source.name |
| update_by_query | ↑ | ↑ |
| reindex | ↑ | ↑ |
| search | doc["field_name"].value | doc["name"].value |
| script_score | ↑ | ↑ |
| script_fields | params._source.field_name | params._source.name |
| sort_script | ↑ | ↑ |
| scripted_metric | ↑ | ↑ |
注:↑表示這一行跟上一行是一樣的
inline Script
pipeline
例子:自定義processor腳本
PUT /_ingest/pipeline/hot_city_pipeline_script
{
"description": "測(cè)試hot ctiy的pipeline",
"processors": [
{
"script": {
"source": """
ctx.total = ctx.hot + ctx.count
""",
"params": {
// ctx._index = 'hot_city';
// ctx._type = '_doc';
}
}
}
]
}
update script
例子:為文檔1的count加上操作數(shù)
POST /hot_city/_update/1
{
"script" : {
"source": "ctx._source.count += params.count",
"params" : {
"count" : 10
}
}
}
update_by_query
例子:通過(guò)腳本增加字段
POST /hot_city/_update_by_query?conflicts=proceed
{
"script": {
"source": """
try
{
Integer total = ctx._source.hot + ctx._source.count;
ctx._source.total = total;
}
catch(NullPointerException npe)
{
}
""",
"lang": "painless"
}
}
reindex
POST _reindex
{
"source": {
"index": "hot_city"
},
"dest": {
"index": "hot_city_v1"
},
"script": {
"source": "ctx._source.total = ctx._source.hot + ctx._source.count"
}
}
query script
例子:查詢城市是北京的
GET /hot_city/_search
{
"query": {
"script": {
// "script": "doc['hot'].value > 18"
"script": "doc['city'].value == '北京'"
}
}
}
script_score
例子:自定義算分
GET hot_city/_search
{
"query": {
"function_score": {
"query": {
"match_all": {}
},
"script_score": {
"script": {
"lang": "expression",
"source": "_score * doc['hot']"
}
}
}
}
}
script_fields
例子:將原字段拼接為一個(gè)新的格式化之后的字段
GET hot_city/_search
{
"script_fields": {
"formative": {
"script": {
"source": "params._source.city + ( params.markup * params._source.hot )",
"params": {
"markup": 0.2
}
}
}
}
}
sort_script
例子:自定義排序規(guī)則
GET hot_city/_search
{
"sort": [
{
"_script": {
"type": "number",
"script": {
"source": """
return params._source.hot + (params._source.count / params.base * params.markup)
""",
"params": {
"markup": 0.1,
"base": 10000
}
},
"order": "desc"
}
}
]
}
scripted_metric
例子:scripted_metric,自定義腳本指標(biāo)統(tǒng)計(jì)
GET /hot_city/_search
{
"size": 0,
"aggs": {
"group_by_ctiy": {
"terms": {
"field": "city",
"size": 10
},
"aggs": {
"profile": {
"scripted_metric": {
"init_script": "state.datas = []",
"map_script": """
Map map = new HashMap();
map.put("name", params._source.city);
map.put("num", params._source.hot + params._source.count);
state.datas.add(map);
""",
"combine_script": """
double profit = 0; for (t in state.datas) { profit += t.num } return profit;
""",
"reduce_script": "double profit = 0; for (a in states) { profit += a } return profit;"
}
}
}
}
}
}
stored script
保存及使用script
大部分情況我們會(huì)將腳本保存到節(jié)點(diǎn)中,那要如何操作呢?
- 語(yǔ)法
POST _scripts/腳本名稱
{
"script": {
"lang": "painless", // 使用的腳本語(yǔ)言,必填
"source": "" // 腳本內(nèi)容,必填
}
}
例子:增加熱門(mén)城市的熱度
POST _scripts/hot_city_update_count
{
"script": {
"lang": "painless",
"source": "ctx._source.count += params.count"
}
}
使用保存的腳本進(jìn)行更新
POST /hot_city/_update/1
{
"script": {
"id": "hot_city_update_count",
"params": {
"count": 1
}
}
}
注意:上面所有的inline腳本我們都可以保存在節(jié)點(diǎn)中,只是看場(chǎng)景而已。
緩存
es 會(huì)將腳本(inline和stored)緩存起來(lái),可在elasticsearch.yml文件中做出更改
| 屬性 | 釋義 |
|---|---|
| script.cache.max_size | 設(shè)置可緩存腳本的最大值,默認(rèn)為100 |
| script.cache.expire | 設(shè)置緩存腳本的有效期 |
| script.max_compilations_rate | 默認(rèn)每5分鐘最多編譯75次 |
| script.max_size_in_bytes | 存儲(chǔ)腳本的大小限制為65535字節(jié) |