原英文版地址: https://www.elastic.co/guide/en/elasticsearch/reference/7.7/modules-scripting-using.html, 原文档版权归 www.elastic.co 所有
本地英文版地址: ../en/modules-scripting-using.html

如何使用脚本

只要是Elasticsearch API中支持脚本的地方,语法都遵循相同的模式:

  "script": {
    "lang":   "...",  
    "source" | "id": "...", 
    "params": { ... } 
  }

编写脚本的语言,默认为painless

可以被指定为内联脚本的source或存储脚本的id的脚本本身。

应该传递到脚本中的任何命名参数。

例如,下面的脚本在搜索请求中用于返回脚本字段(scripted field)

PUT my_index/_doc/1
{
  "my_field": 5
}

GET my_index/_search
{
  "script_fields": {
    "my_doubled_field": {
      "script": {
        "lang":   "expression",
        "source": "doc['my_field'] * multiplier",
        "params": {
          "multiplier": 2
        }
      }
    }
  }
}

脚本参数

lang
指定编写脚本的语言。默认为painless
source, id
指定脚本的源(source)。 如上例所示,内联(inline)脚本被指定为源(source)。 存储的(stored)脚本是指定id,并从集群状态中检索(请参见存储的脚本)。
params
指定作为变量传递到脚本中的任何命名参数。

首选参数

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

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

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

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

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

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

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

短脚本形式(short script form)

为了简洁,可以使用简短的脚本形式。 短形式下,script由字符串而不是对象表示。 该字符串包含脚本的源(source)。

脚本的简短形式:

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

而相同脚本的一般形式是:

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

存储的脚本

可以使用_scripts终端在集群状态中存储和检索脚本。

如果启用了Elasticsearch安全功能,你必须拥有以下权限才能创建、检索和删除存储的脚本:

  • cluster: allmanage

有关更多信息,请参见安全权限

请求示例

下面是一个使用位于/_scripts/{id}的存储脚本的示例。

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

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

你还可以指定一个上下文作为url路径的一部分,以/_scripts/{id}/{context}的形式根据该特定上下文编译存储的脚本:

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

同样的脚本可以通过以下方式检索:

GET _scripts/calculate-score

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

GET twitter/_search
{
  "query": {
    "script_score": {
      "query": {
        "match": {
            "message": "some message"
        }
      },
      "script": {
        "id": "calculate-score",
        "params": {
          "my_modifier": 2
        }
      }
    }
  }
}

删除脚本:

DELETE _scripts/calculate-score

搜索模板(search templates)

还可以使用_scripts API来存储搜索模板(search templates)。 搜索模板保存带有占位符值(称为模板参数)的特定搜索请求

你可以使用存储的搜索模板来运行搜索,而无需写出整个查询。 只需提供存储模板的ID和模板参数。 当你希望快速无误地运行常用查询时,这很有用。

搜索模板使用mustache模板语言。 更多详情和示例请参见搜索模板

脚本缓存

默认情况下,所有脚本都会被缓存,它们只需要在变更时重新编译。 默认情况下,脚本没有过期时间,但是你可以通过使用script.cache.expire设置来更改此行为。 可以使用script.cache.max_size设置来配置此缓存的个数。 默认情况下,缓存的脚本的个数为100

脚本的大小限制为65,535字节。 这可以通过设置script.max_size_in_bytes设置来增加该软限制,但如果脚本非常大,则应考虑使用原生脚本引擎(native script engine)

脚本错误

当存在编译或运行时异常时,Elasticsearch会返回错误的详细信息。 此响应的内容有助于跟踪问题。

此功能是试验性的,在未来的版本中可能会被更改或完全删除。 Elastic将尽最大努力解决任何问题,但实验功能不受官方GA功能的支持SLA的约束。

position的内容是实验性的,可能会发生变化。