美文网首页
Elasticsearch 7.x 深入【13】Script

Elasticsearch 7.x 深入【13】Script

作者: 孙瑞锴 | 来源:发表于2020-06-06 22:58 被阅读0次

1. 借鉴

极客时间 阮一鸣老师的Elasticsearch核心技术与实战
官网 modules-scripting-using
官网 painless-execute-api
官网 Painless Scripting Language
Elasticsearch Painless script编程

2. 开始

script在很多场景下都有使用到,我们这次来看下

结构

"script": {
  "lang": "painless" // 脚本语言:painless(默认),expression,可省略
  "source": """  // 脚本内容(inline脚本)
    这里面是脚本
  """,
  "id": "" // 脚本的ID(stored脚本),source和ID只能存在一个
  "params": { // source里面需要的参数
    "key1": value1,
    "key2": value2
  }
}

注意:本篇文章所有脚本,lang为painless

上下文

在不同的上下文中,获取文档字段使用的语法是不同的。

上下文 语法 示例:获取文档中的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": "测试hot ctiy的pipeline",
  "processors": [
    {
      "script": {
        "source": """
          ctx.total = ctx.hot + ctx.count
        """,
        "params": {
          // ctx._index = 'hot_city';
          // ctx._type = '_doc';
          
        }
      }
    }
  ]
}

update script

例子:为文档1的count加上操作数

POST /hot_city/_update/1
{
   "script" : {
     "source": "ctx._source.count += params.count",
     "params" : {
        "count" : 10
     }
   }
}

update_by_query

例子:通过脚本增加字段

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

例子:将原字段拼接为一个新的格式化之后的字段

GET hot_city/_search
{
  "script_fields": {
    "formative": {
      "script": {
        "source": "params._source.city + ( params.markup * params._source.hot )",
        "params": {
          "markup": 0.2
        }
      }
    }
  }
}

sort_script

例子:自定义排序规则

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,自定义脚本指标统计

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

大部分情况我们会将脚本保存到节点中,那要如何操作呢?

  • 语法
POST _scripts/脚本名称
{
  "script": {
    "lang": "painless",  // 使用的脚本语言,必填
    "source": "" // 脚本内容,必填
  }
}

例子:增加热门城市的热度

POST _scripts/hot_city_update_count
{
  "script": {
    "lang": "painless", 
    "source": "ctx._source.count += params.count"
  }
}

使用保存的脚本进行更新

POST /hot_city/_update/1
{
  "script": {
    "id": "hot_city_update_count",
    "params": {
      "count": 1
    }
  }
}

注意:上面所有的inline脚本我们都可以保存在节点中,只是看场景而已。

缓存

es 会将脚本(inline和stored)缓存起来,可在elasticsearch.yml文件中做出更改

属性 释义
script.cache.max_size 设置可缓存脚本的最大值,默认为100
script.cache.expire 设置缓存脚本的有效期
script.max_compilations_rate 默认每5分钟最多编译75次
script.max_size_in_bytes 存储脚本的大小限制为65535字节

3. 大功告成

相关文章

网友评论

      本文标题:Elasticsearch 7.x 深入【13】Script

      本文链接:https://www.haomeiwen.com/subject/oioszhtx.html