Home > Software engineering >  ElasticSearch aggregation - buckets/scripted_metric
ElasticSearch aggregation - buckets/scripted_metric

Time:12-13

i try to calculate rate function rate(val,ts)= v2-v1/t2-t1 for each document in my index.

My mappings are in form : { "name":keyword","value":"double","timestamp":"integer"}.

So for an example if i have 2 documents in my index:

doc1:{"name":name1,"value":5,"timestamp":2 } doc2: {name":name1,"value":10,"timestamp":3 },

i need to get result(ts=3) = (10-5)/(3-2).

Is there any way to do this in elasticsearch?

I tried to write my own metric script in this form :

GET test1/_search
{
"size":15,
"aggs":{
  "sum_the_hard_way": {
    "scripted_metric": {
      "init_script": {
        "source": "state.values = []; state.timestamps = [];"
      },
      "map_script": {
        "source": "state.values.add(doc['value'].value);state.timestamps.add(doc['timestamp'].value);"
      },
      "combine_script": {
        "source": "def rates = []; for ( int i = 0; i <= state.values.size()-1 ; i   ) { rate[i 1] = (state.value[i 1]- state.value[i])/(state.timestamp[i 1]- state.timestamp[i]);} return values"
      },
      "reduce_script": {
        "source": "def vals = []; for (a in states) { vals.add(a) } return vals"
      }
    }
  }
}
}

But it doesn't work, i got

"reason" : "index_out_of_bounds_exception: Index 0 out of bounds for length

Thank you in advance!

CodePudding user response:

TLDR;

Some type slipped into your code. I hope I have fixed it.

GET /so_agg_painless/_search
{
  "size":15,
  "aggs":{
    "sum_the_hard_way": {
      "scripted_metric": {
        "init_script": {
          "source": """
            state.values = [];
            state.timestamps = [];
          """
        },
        "map_script": {
          "source": """
            state.values.add(doc['value'].value);
            state.timestamps.add(doc['timestamp'].value);
          """
        },
        "combine_script": {
          "source": """
            def rates = [];
            for ( int i = 0; i <= state.values.size()-2 ; i   ) {
              def nom = (state.values[i 1]- state.values[i]);
              def denom = (state.timestamps[i 1]- state.timestamps[i]);
              rates.add(nom/denom);
            } 
            return rates
            """
        },
        "reduce_script": {
          "source": """
            def vals = [];
            for (a in states) { 
              vals.add(a) 
            }
            return vals
            """
        }
      }
    }
  }
}

Hey man, you have many typos in your code, that's why it is failing. But I think the logic is perfect so kudos to you, so were super close.

You need to pay attention to those s in your code.

Also as you may see in the code I posted. use the """. So you can indent the code it makes it wayyy easier to read and fix.

  • Related