Elasticsearch Painless Script详解

本文介绍了Elasticsearch中Painless脚本的基础知识及其应用案例,包括文档处理、字段计算等功能,强调了其高性能与安全性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. Painless 简介

自 ES 5.x 后引入,专门为 ES 设置,扩展了 Java 的语法
6.0 开始,ES 只支持 Painless。Grooby ,JavaScript 和 Python 都不在支持
Painless 支持所有的 Java 的数据类型及 Java API 子集
Painless Script 具备以下特性

  • 高性能 、 安全
  • 支持显示类型或者动态定义类型

Painless 的用途

Painless 可以对文档字段进行加工处理

  • 更新或者删除字段,处理数据聚合操作
  • Script Field: 对返回的字段提前进行计算
  • Function Score:对文档的算分进行处理

在 Ingest Pipeline 中执行脚本
在 Reindex API,Update By Query 时,对数据进行处理

  • 脚本编写的语言,默认为painless。
  • 脚本本身可以指定为内联脚本的source或存储脚本的id。
  • 应传递给脚本的任何命名参数。

2. 参数

lang

  • 指定编写脚本的语言,默认为painless。

source,id

  • 指定脚本的来源,inline脚本是指定source,,存储的脚本是指定的id,并从群集状态中检索(请参阅存储的脚本)。

params

  • 指定作为变量传递到脚本的任何命名参数。

3. 首选参数

Elasticsearch第一次看到一个新脚本,它会编译它并将编译后的版本存储在缓存中,编译可能是一个繁重的过程。

如果需要将变量传递给脚本,则应将它们作为命名参数传递给脚本本身而不是硬编码值,例如,如果你希望能够将字段值乘以不同的乘数,请不要将乘数硬编码到脚本中:

"source": "doc['my_field'] * 2"

相反,将其作为命名参数传递:

  "source": "doc['my_field'] * multiplier",
  "params": {
    "multiplier": 2
  }

第一个版本每次乘数改变时都必须重新编译,第二个版本只编译一次。

如果你在很短的时间内编译了太多独特的脚本,Elasticsearch将使用circuit_breaking_exception错误拒绝新的动态脚本。默认情况下,每分钟将编译最多15个内联脚本,你可以通过设置script.max_compilations_rate动态更改此设置。

4. 简短脚本形式

可以使用简短脚本形式来简化,在简短形式中,script由字符串而不是对象表示,该字符串包含脚本的源。

简写:

"script": "ctx._source.likes++"

正常形式的相同脚本:

  "script": {
    "source": "ctx._source.likes++"
  }

5. 通过 Painless 脚本访问字段

上下文语法
Ingestionctx.field_name
Updatectx._source.field_name
Search & Aggregationdoc[“field_name”]

6. 示例

6.1 案例 1:Script Processsor

在这里插入图片描述

# 增加一个 Script Prcessor
POST _ingest/pipeline/_simulate
{
  "pipeline": {
    "description": "to split blog tags",
    "processors": [
      {
        "split": {
          "field": "tags",
          "separator": ","
        }
      },
      {
        "script": {
          "source": """
          if(ctx.containsKey("content")){
            ctx.content_length = ctx.content.length();
          }else{
            ctx.content_length=0;
          }
        """
        }
      },
      {
        "set": {
          "field": "views",
          "value": 0
        }
      }
    ]
  },
  "docs": [
    {
      "_index": "index",
      "_id": "id",
      "_source": {
        "title": "Introducing big data......",
        "tags": "hadoop,elasticsearch,spark",
        "content": "You konw, for big data"
      }
    },
    {
      "_index": "index",
      "_id": "idxx",
      "_source": {
        "title": "Introducing cloud computering",
        "tags": "openstack,k8s",
        "content": "You konw, for cloud"
      }
    }
  ]
}

6.2 案例 2:文档更新计数

在这里插入图片描述

DELETE tech_blogs
PUT tech_blogs/_doc/1
{
  "title":"Introducing big data......",
  "tags":"hadoop,elasticsearch,spark",
  "content":"You konw, for big data",
  "views":0
}

POST tech_blogs/_update/1
{
  "script": {
    "source": "ctx._source.views += params.new_views",
    "params": {
      "new_views":100
    }
  }
}

# 查看views计数
POST tech_blogs/_search

6.3 案例 3:搜索时的 Script 字段

在这里插入图片描述

GET tech_blogs/_search
{
  "script_fields": {
    "rnd_views": {
      "script": {
        "lang": "painless",
        "source": """
          java.util.Random rnd = new Random();
          doc['views'].value+rnd.nextInt(1000);
        """
      }
    }
  },
  "query": {
    "match_all": {}
  }
}

6.4 Script :Inline v.s Stored

在这里插入图片描述

#保存脚本在 Cluster State
POST _scripts/update_views
{
  "script":{
    "lang": "painless",
    "source": "ctx._source.views += params.new_views"
  }
}

POST tech_blogs/_update/1
{
  "script": {
    "id": "update_views",
    "params": {
      "new_views":1000
    }
  }
}

6.5 示例4

首先,在集群状态下创建名为calculate-score的脚本:

POST _scripts/calculate-score
{
  "script": {
    "lang": "painless",
    "source": "Math.log(_score * 2) + params.my_modifier"
  }
}

可以使用以下命令检索相同的脚本:

GET _scripts/calculate-score

可以通过指定id参数来使用存储的脚本,如下所示:

GET _search
{
  "query": {
    "script": {
      "script": {
        "id": "calculate-score",
        "params": {
          "my_modifier": 2
        }
      }
    }
  }
}

删除:

DELETE _scripts/calculate-score

3. 缓存

编译的开销相较大
Elasticsearch 会将脚本编译后缓存在 Cache 中

  • Inline scripts 和 Stored Scripts 都会被缓存
  • 默认缓存 100 个脚本
    在这里插入图片描述
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值