首页 > 解决方案 > 无痛脚本错误 - “已达到可在循环中执行的最大语句数”

问题描述

我有一个简单的脚本,我试图在 elasticsearch 中执行,以根据现有字段的值向现有文档添加新字段。这是我要更新的源文档-

"_source" : {
    "mpmNumber" : "4004749",
    "parentTitles" : [
      {
        "parentUri" : "entities/YYYYY",
        "parentType" : "configuration/entityTypes/Title",
        "parentLabel" : "Gilmore Girls - YR01 00/01 - Season 1 - XXXXX",
        "parentDirectionalLabel" : "is parent of",
        "originallyAiredAs" : "5",
        "uri" : "relations/ZZZZZ",
        "type" : "configuration/entityTypes/Title",
        "label" : "Cinnamon's Wake - Episode 5 - ZZZZZ",
        "directionalLabel" : "is child of"
      }
    ]
  }

我基本上是在尝试解析parentLabel字符串的内容并提取各个值,因此可以使用各个值来创建新字段。这是我的脚本 -

{
  "script":{
    "lang": "painless",
    "source":"""

      def splitText(def str, def separator)
      {
        def pos=str.indexOf(separator);
        def result=[];
        while (pos>0)
        {
          def split=str.substring(0,pos);
          def rest=str.substring(pos+2,str.length());
          result.add(split);
          pos=rest.indexOf(separator);
          if(pos==-1)
          {
            result.add(rest);
          }
        }
        return result;
      }

      def parentLabelArray=splitText(ctx._source.parentTitles[0].parentLabel,'-');

      String parentTitle=parentLabelArray[0]+parentLabelArray[1];
      String parentType=parentLabelArray[2];
      String parentId=parentLabelArray[3];

      ctx._source.parentTitles[0].parentTitle=parentTitle;
      ctx._source.parentTitles[0].parentType=parentType.substring(0,parentType.length()-3);
      ctx._source.parentTitles[0].parentAiringOrder=parentType.substring(parentType.length()-3,parentType.length());
      ctx._source.parentTitles[0].parentId=parentId;

  """
  }
}

但是,当我尝试执行此脚本时,我不断收到以下错误 -

{
  "error": {
    "root_cause": [
      {
        "type": "remote_transport_exception",
        "reason": "[xDrtBOW][x.x.x.x:9300][indices:data/write/update[s]]"
      }
    ],
    "type": "illegal_argument_exception",
    "reason": "failed to execute script",
    "caused_by": {
      "type": "script_exception",
      "reason": "runtime error",
      "script_stack": [
        "while (pos>0)\n        {\n          def ",
        "^---- HERE"
      ],
      "script": "      def splitText(def str, def separator)\n      {\n        def pos=str.indexOf(separator);\n        def result=[];\n        while (pos>0)\n        {\n          def split=str.substring(0,pos);\n          def rest=str.substring(pos+2,str.length());\n          result.add(split);\n          pos=rest.indexOf(separator);\n          if(pos==-1)\n          {\n            result.add(rest);\n          }\n        }\n        return result;\n      }\n      \n      def parentLabelArray=splitText(ctx._source.parentTitles[0].parentLabel,'-');\n      \n      String parentTitle=parentLabelArray[0]+parentLabelArray[1];\n      String parentType=parentLabelArray[2];\n      String parentId=parentLabelArray[3];\n      \n      ctx._source.parentTitles[0].parentTitle=parentTitle;\n      ctx._source.parentTitles[0].parentType=parentType.substring(0,parentType.length()-3);\n      ctx._source.parentTitles[0].parentAiringOrder=parentType.substring(parentType.length()-3,parentType.length());\n      ctx._source.parentTitles[0].parentId=parentId;",
      "lang": "painless",
      "caused_by": {
        "type": "painless_error",
        "reason": "The maximum number of statements that can be executed in a loop has been reached."
      }
    }
  },
  "status": 400
}

知道为什么我会得到这个以及如何解决它吗?

标签: elasticsearchelasticsearch-painless

解决方案


您基本上重新实现了该split方法。使用它要容易得多。

我对您的脚本进行了一些更改,如下所示:

  def parentLabelArray=/\-/.split(ctx._source.parentTitles[0].parentLabel);

  String parentTitle=parentLabelArray[0].trim()+parentLabelArray[1].trim();
  String parentType=parentLabelArray[2].trim();
  String parentId=parentLabelArray[3].trim();

  ctx._source.parentTitles[0].parentTitle=parentTitle;
  ctx._source.parentTitles[0].parentType=parentType.substring(0,parentType.length());
  ctx._source.parentTitles[0].parentAiringOrder=parentType.substring(parentType.length(),parentType.length());
  ctx._source.parentTitles[0].parentId=parentId;

使用该修复程序更新您的文档时,我得到以下信息:

{
"mpmNumber" : "4004749",
"parentTitles" : [
  {
    "parentAiringOrder" : "",
    "parentUri" : "entities/YYYYY",
    "parentLabel" : "Gilmore Girls - YR01 00/01 - Season 1 - XXXXX",
    "parentDirectionalLabel" : "is parent of",
    "directionalLabel" : "is child of",
    "label" : "Cinnamon's Wake - Episode 5 - ZZZZZ",
    "originallyAiredAs" : "5",
    "type" : "configuration/entityTypes/Title",
    "uri" : "relations/ZZZZZ",
    "parentTitle" : "Gilmore GirlsYR01 00/01",
    "parentType" : "Season 1",
    "parentId" : "XXXXX"
  }
]
}

更新:

对于在 AWS 上运行的倒霉蛋,这里是该splitText方法的另一个版本,无需启用正则表达式:

  def splitText(def str, def separator)
  {
     def tokenizer = new StringTokenizer(str, separator);
     def results = [];

     while(tokenizer.hasMoreTokens())
        results.add(tokenizer.nextToken());

     return results;
  }

推荐阅读