Scripted_metric: _agg variable not defined


(Michel Krämer) #1

Hi!

I'm trying to run a scripted_metric aggregation but I keep getting the same error. Here is what I do:

docker run -it -p 9200:9200 elasticsearch

curl -X PUT http://localhost:9200/index

curl -X POST -d '{
    "query" : {
        "match_all" : {}
    },
    "aggs": {
        "profit": {
            "scripted_metric": {
                "init_script" : "_agg['transactions'] = []",
                "map_script" : "if (doc['type'].value == \"sale\") { _agg.transactions.add(doc['amount'].value) } else { _agg.transactions.add(-1 * doc['amount'].value) }",
                "combine_script" : "profit = 0; for (t in _agg.transactions) { profit += t }; return profit",
                "reduce_script" : "profit = 0; for (a in _aggs) { profit += a }; return profit"
            }
        }
    }
}' "http://localhost:9200/index/type/_search?pretty"

I took this aggregation from the documentation (https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-metrics-scripted-metric-aggregation.html) but it doesn't matter what I do I always get the following error:

{
  "error" : {
    "root_cause" : [
      {
        "type" : "script_exception",
        "reason" : "compile error",
        "script_stack" : [
          "_agg[transactions] = []",
          "^---- HERE"
        ],
        "script" : "_agg[transactions] = []",
        "lang" : "painless"
      }
    ],
    "type" : "search_phase_execution_exception",
    "reason" : "all shards failed",
    "phase" : "query",
    "grouped" : true,
    "failed_shards" : [
      {
        "shard" : 0,
        "index" : "index",
        "node" : "Nrcqm2e-TxGLI7wYR4kfgw",
        "reason" : {
          "type" : "script_exception",
          "reason" : "compile error",
          "caused_by" : {
            "type" : "illegal_argument_exception",
            "reason" : "Variable [_agg] is not defined."
          },
          "script_stack" : [
            "_agg[transactions] = []",
            "^---- HERE"
          ],
          "script" : "_agg[transactions] = []",
          "lang" : "painless"
        }
      }
    ],
    "caused_by" : {
      "type" : "script_exception",
      "reason" : "compile error",
      "caused_by" : {
        "type" : "illegal_argument_exception",
        "reason" : "Variable [_agg] is not defined."
      },
      "script_stack" : [
        "_agg[transactions] = []",
        "^---- HERE"
      ],
      "script" : "_agg[transactions] = []",
      "lang" : "painless"
    }
  },
  "status" : 500
}

Any idea what I'm doing wrong? Thanks for your help!

Cheers,
Michel


(Daniel Mitterdorfer) #2

Hi @michel-kraemer,

the default scripting language changed with Elasticsearch 5.0 from Groovy to Painless but unfortunately, the documentation does not reflect this (update: I've raised #21536). To make it work, you need to specify the scripting language explicitly:

GET /test/_search
{
   "query": {
      "match_all": {}
   },
   "aggs": {
      "profit": {
         "scripted_metric": {
            "params": {
               "_agg": {}
            },
            "init_script": {
               "lang": "groovy",
               "inline": "_agg['transactions'] = []"
            },
            "map_script": {
               "lang": "groovy",
               "inline": "if (doc['type'].value == \"sale\") { _agg.transactions.add(doc['amount'].value) } else { _agg.transactions.add(-1 * doc['amount'].value) }"
            },
            "combine_script": {
               "lang": "groovy",
               "inline": "profit = 0; for (t in _agg.transactions) { profit += t }; return profit"
            },
            "reduce_script": {
               "lang": "groovy",
               "inline": "profit = 0; for (a in _aggs) { profit += a }; return profit"
            }
         }
      }
   }
}

Please also ensure that you allow inline scripts by adding the following line to conf/elasticsearch.yml:

script.inline: true

Daniel


(Michel Krämer) #3

Thanks, Daniel!

I see. This explains a lot! Thanks for opening the issue.

Does that mean you cannot write a scripted_metric aggregation with painless?

Michel


(Daniel Mitterdorfer) #4

Hi @michel-kraemer,

You can write such an aggregation with Painless. It's just that the documentation was not up to date. Nik fixed the ticket already and you can see now in the docs how to write a scripted_metric aggregation with Painless

Daniel


(system) #5

This topic was automatically closed 28 days after the last reply. New replies are no longer allowed.