Why is this scripted metric aggregation query not working?

PUT /ledger/_doc/1
{
"type":"sale"
}

PUT /ledgeramt/_doc/1
{
"amount":1000
}

POST /ledger,ledgeramt/_search?size=0
{
"query" : {
"match_all" : {}
},
"aggs": {
"profit": {
"scripted_metric": {
"init_script" : "params._agg.transactions = ",
"map_script" : "params._agg.transactions.add(doc['type'].value == \u0027sale\u0027 ? doc['amount'].value : -1 * doc['amount'].value)",
"combine_script" : "double profit = 0; for (t in params._agg.transactions) { profit += t } return profit",
"reduce_script" : "double profit = 0; for (a in params._aggs) { profit += a } return profit"
}
}
}
}

Error:

{
"took": 10,
"timed_out": false,
"_shards": {
"total": 10,
"successful": 8,
"skipped": 0,
"failed": 2,
"failures": [
{
"shard": 3,
"index": "ledger",
"node": "6nKisyggQtmWdv_NVXPXjQ",
"reason": {
"type": "script_exception",
"reason": "runtime error",
"script_stack": [
"org.elasticsearch.search.lookup.LeafDocLookup.get(LeafDocLookup.java:81)",
"org.elasticsearch.search.lookup.LeafDocLookup.get(LeafDocLookup.java:39)",
"params._agg.transactions.add(doc['type'].value == 'sale' ? doc['amount'].value : -1 * doc['amount'].value)",
" ^---- HERE"
],
"script": "params._agg.transactions.add(doc['type'].value == 'sale' ? doc['amount'].value : -1 * doc['amount'].value)",
"lang": "painless",
"caused_by": {
"type": "illegal_argument_exception",
"reason": "No field found for [amount] in mapping with types "
}
}
}
]
},
"hits": {
"total": 0,
"max_score": 0,
"hits":
},
"aggregations": {
"profit": {
"value": 0
}
}
}

Is this not allowed? I am on ELK 6.2.1

Thanks.

Anybody there? Please suggest. Thanks

The error is exactly what is stated in the response. The amount field does not exist in your index:

"reason": "No field found for [amount] in mapping with types []"

You should double check the rest of your script as well, though. For example, there is not in operator in painless, and variables must have a type, even if that type is def. I think mean to use the enhanced for loop, which uses colon (:).

for (def t : params._agg.transactions)

Thanks @rjernst. But that's not the issue. I still get the same error. Here I am reading from 2 indexes.. How to create script for that? Thanks

POST /ledger,amt/_search?size=0
{
"query" : {
"match_all" : {}
},
"aggs": {
"profit": {
"scripted_metric": {
"init_script" : "params._agg.transactions = []",
"map_script" : "params._agg.transactions.add(doc['typ'].value == \u0027sale\u0027 ? doc['amount'].value : -1 * doc['amount'].value)",
"combine_script" : "double profit = 0; for (def t: params._agg.transactions) { profit += t } return profit",
"reduce_script" : "double profit = 0; for (def a: params._aggs) { profit += a } return profit"
}
}
}
}

The mapping must exist in both indexes, or you need to make your script work when the field does not exist. You can check for the mapping existing by doing doc.containsKey('amount').

It worked. Thanks @rjernst.

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