Rom*_*man 1 function elasticsearch elasticsearch-painless
我正在尝试使用一个例子
https://www.elastic.co/guide/en/elasticsearch/reference/6.4/modules-scripting-using.html
我创建了一个函数并保存了它。
POST http://localhost:9200/_scripts/calculate-score
{
"script": {
"lang": "painless",
"source": "ctx._source.added + params.my_modifier"
}
}
Run Code Online (Sandbox Code Playgroud)
尝试调用保存的函数
POST http://localhost:9200/users/user/_search
{
"query": {
"script": {
"script": {
"id": "calculate-score",
"params": {
"my_modifier": 2
}
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
它返回一个错误:Variable [ctx] is not defined。我尝试使用doc['added']但收到相同的错误。请帮助我了解如何调用该函数。
您应该尝试使用doc['added'].value,让我向您解释原因和方法。简而言之,因为无痛脚本语言相当简单但晦涩难懂。
ctx变量?它找不到ctx变量的原因是因为这个无痛脚本在“过滤器上下文”中运行,而这样的变量在过滤器上下文中不可用。(如果你很好奇,从 ES 6.4 开始有18 种类型的无痛上下文)。
在过滤器上下文中,只有两个变量可用:
params(地图,只读)作为查询的一部分传入的用户定义的参数。
doc(地图,只读)包含当前文档的字段,其中每个字段都是一个值列表。
doc['added'].value在您的情况下使用它应该足够了:
POST /_scripts/calculate-score
{
"script": {
"lang": "painless",
"source": "doc['added'].value + params.my_modifier"
}
}
Run Code Online (Sandbox Code Playgroud)
应该,因为如果我们尝试执行它会出现另一个问题(就像你所做的那样):
"type": "script_exception",
"reason": "runtime error",
"script_stack": [
"doc['added'].value + params.my_modifier",
"^---- HERE"
],
"script": "calculate-score",
"lang": "painless",
"caused_by": {
"type": "class_cast_exception",
"reason": "cannot cast def [long] to boolean"
}
Run Code Online (Sandbox Code Playgroud)
由于其上下文,此脚本应返回boolean:
返回
boolean返回
true是否应作为查询结果返回当前文档,false否则返回。
在这一点上,我们可以理解为什么您尝试执行的脚本对 Elasticsearch 没有多大意义:它应该判断文档是否与脚本查询匹配。如果脚本返回一个整数,Elasticsearch 将不知道它是true还是false。
例如,我们可以使用以下脚本:
POST /_scripts/calculate-score1
{
"script": {
"lang": "painless",
"source": "doc['added'].value > params.my_modifier"
}
}
Run Code Online (Sandbox Code Playgroud)
现在我们可以访问脚本:
POST /users/user/_search
{
"query": {
"script": {
"script": {
"id": "calculate-score1",
"params": {
"my_modifier": 2
}
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
它将返回所有added大于 2 的文档:
"hits": [
{
"_index": "users",
"_type": "user",
"_id": "1",
"_score": 1,
"_source": {
"name": "John Doe",
"added": 40
}
}
]
Run Code Online (Sandbox Code Playgroud)
这次脚本返回了 aboolean并且 Elasticsearch 设法使用了它。
如果您好奇,range查询可以完成相同的工作,而无需编写脚本。
.value后面doc['added']?如果您尝试doc['added']直接访问,您可能会注意到错误消息有所不同:
POST /_scripts/calculate-score
{
"script": {
"lang": "painless",
"source": "doc['added'] + params.my_modifier"
}
}
"type": "script_exception",
"reason": "runtime error",
"script_stack": [
"doc['added'] + params.my_modifier",
" ^---- HERE"
],
"script": "calculate-score",
"lang": "painless",
"caused_by": {
"type": "class_cast_exception",
"reason": "Cannot apply [+] operation to types [org.elasticsearch.index.fielddata.ScriptDocValues.Longs] and [java.lang.Integer]."
}
Run Code Online (Sandbox Code Playgroud)
无痛再次向我们展示了它的晦涩之处:当访问'added'文档的字段时,我们获得了一个实例org.elasticsearch.index.fielddata.ScriptDocValues.Longs,Java 虚拟机拒绝将其添加到一个整数(我们不能在这里责怪 Java)。
所以我们必须实际调用.getValue()方法,它在无痛翻译中就是简单的.value.
如果您想在added某个文档的字段中添加 2并保存更新的文档怎么办?更新 API可以做到这一点。
它在update context 中运行,实际上已经ctx定义了变量,而后者又可以通过ctx['_source'].
我们可能会创建一个新脚本:
POST /_scripts/add-some
{
"script": {
"lang": "painless",
"source": "ctx['_source']['added'] += params.my_modifier"
}
}
Run Code Online (Sandbox Code Playgroud)
现在我们可以使用它:
POST /users/user/1/_update
{
"script" : {
"id": "add-some",
"params" : {
"my_modifier" : 2
}
}
}
Run Code Online (Sandbox Code Playgroud)
显然,因为这是错误的。此脚本(来自此文档页面):
POST _scripts/calculate-score
{
"script": {
"lang": "painless",
"source": "Math.log(_score * 2) + params.my_modifier"
}
}
Run Code Online (Sandbox Code Playgroud)
稍后在过滤器上下文中执行(在搜索请求中,在script查询中),而且,正如我们现在所知,没有_score可用的变量。
当运行允许摆动文档的相关性分数的查询时,此脚本仅在分数上下文中才有意义。funtion_score
我想说的是,一般情况下,建议避免使用脚本,因为它们的性能很差。
| 归档时间: |
|
| 查看次数: |
3897 次 |
| 最近记录: |