【问题标题】:Elasticsearch failed to execute scriptElasticsearch 执行脚本失败
【发布时间】:2021-05-18 10:33:51
【问题描述】:

Elasticsearch 7.7.0 版

这是映射的一部分:

const PROFILE_MAPPING = {
  mappings: {
    properties: {
      _userLocation: {
        type: "geo_point"
      },
      _ignoredBy: {
        type: "nested"
      }
    }
  }
};

_ignoredBy 数据示例:

 [{
        "until" : "2020-12-03T16:20:43.176Z",
        "user" : <USER_ID>
  }]

这是我正在运行以更新它的脚本:


    await client.update({
        index,
        id: target,
        refresh: "wait_for",
        body: {
          script: {
            source:
              "ctx._source._ignoredBy.removeIf(item -> item.user == 
    params.by.user);ctx._source._ignoredBy.add(params.by)",
            params: {
              by: {
                user: initiator,
                until: addSeconds(new Date(), ignoreInterval) 
              }
            }
          }
        }
      });

这是我得到的错误:

    {
      "error": {
        "root_cause": [
          {
            "type": "illegal_argument_exception",
            "reason": "failed to execute script"
          }
        ],
        "type": "illegal_argument_exception",
        "reason": "failed to execute script",
        "caused_by": {
          "type": "script_exception",
          "reason": "runtime error",
          "script_stack": ["item -> item.user == params.by.user);", "^---- HERE"],
          "script": "ctx._source._ignoredBy.removeIf(item -> item.user == params.by.user);ctx._source._ignoredBy.add(params.by)",
          "lang": "painless",
          "position": { "offset": 32, "start": 32, "end": 69 },
          "caused_by": { "type": "null_pointer_exception", "reason": null }
        }
      },
      "status": 400
    }

奇怪的是,这在 99% 的情况下都有效,但错误却出现在日志中,并且无法找出原因。传入的参数 100% 显示在日志中。

【问题讨论】:

    标签: elasticsearch elasticsearch-painless


    【解决方案1】:

    这样的空指针很难理解,但我的直觉是ctx._source._ignoredBy 本身有些问题。

    本着这种精神,我建议在调用 .removeIf 之前再添加一个检查 - 也许初始化它以防它是 null

    {
      "script": {
        "source": "if (ctx._source._ignoredBy == null) {ctx._source._ignoredBy = []; }  ctx._source._ignoredBy.removeIf(item -> item.user == params.by.user); ctx._source._ignoredBy.add(params.by)",
        "params": {
          ...
        }
      }
    }
    

    【讨论】:

    • 谢谢乔,如果_ignoredBy 是空的,它是否也会引发空指针,即item 不存在?我根本不懂Java。
    • 信息太少,我无法自信地说,但我认为是的。 Painless 类似于 java,因此适用相同的原则。试一试我的脚本,稍等片刻,看看你是否仍然看到 1% 的错误。
    猜你喜欢
    • 2011-06-28
    • 2021-09-19
    • 2020-11-24
    • 2020-08-19
    • 1970-01-01
    • 1970-01-01
    • 2018-04-29
    • 2018-12-09
    • 2023-03-13
    相关资源
    最近更新 更多