Search code examples
elasticsearchelasticsearch-painless

Elastic painless 'state' alternative


This is my first attempt at a painless script, however almost every example makes use of a 'state' object which is not available in my version.

i.e.

"aggs": {
    "terms": {
      "scripted_metric": {
        "init_script": "state.id_map = [:]; state.sum = 0.0;",
        "map_script": """
          def id = doc['record_id.ID'].value;
          if (!state.id_map.containsKey(id)) {
            state.id_map[id] = true;
            state.sum += doc['VAL'].value;
          }
        """,
        "combine_script": """
            def sum = state.sum;
            def stats = [:];
            stats.sum = sum;
            return stats
        """,
        "reduce_script": "return states"
      }
    }
  }

Result in : Variable [state] is not defined.

Omitting it doesn't help either i.e.

"init_script": "Map id_map = new HashMap(); double sum = 0.0;",
        "map_script": """
          def id = doc['record_id.ID'].value;
          if (!id_map.containsKey(id)) {
            id_map[id] = true;
            sum += doc['VAL'].value;
          }
        """,

Results in: "Variable [id_map] is not defined." in the map_script section

What's the alternative approach for earlier versions ?


Solution

  • The scripts you have above work fine in version 6.4 onwards.

    Since you're running ES 5.x you need to change a little bit the syntax:

    • replace state by params._agg
    • replace states by params._aggs

    Like this:

    "aggs": {
        "terms": {
          "scripted_metric": {
            "init_script": "params._agg.id_map = [:]; params._agg.sum = 0.0;",
            "map_script": """
              def id = doc['record_id.ID'].value;
              if (!params._agg.id_map.containsKey(id)) {
                params._agg.id_map[id] = true;
                params._agg.sum += doc['VAL'].value;
              }
            """,
            "combine_script": """
                def sum = params._agg.sum;
                def stats = [:];
                stats.sum = sum;
                return stats
            """,
            "reduce_script": "return params._aggs"
          }
        }
      }