PrakashT
PrakashT

Reputation: 901

How to use custom script inside aggregation in elasticsearch with nodejs

Here is the my code:

const convertCurrency = async (currrencyType)  => {
    try{
        const res =  await got("https://api.exchangerate-api.com/v4/latest/USD");
        return (JSON.parse(res.body)['rates'][currrencyType]);
    }
    catch(err){
        console.log(err);
    }
}

async function search(){
  try{
    client.search({
      index : '03776182',
      body: {
        aggs : {
          price_ranges : {
              range : {
                  field : "price",
                  script : {source : "convertCurrency(/EUR/) * _value"},
                  ranges : [
                      { "from" : 10, "to" : 20 },
                  ]
              }
          }
      }
      }
  },(err,resp,status)=>{
      err ? console.log(err): console.log(JSON.stringify(resp));
  });
  }
  catch(err){console.log(err);}
}

I am trying to insert the custom script inside the source field. But it gives below error.

 response: `{"error":{"root_cause":[{"type":"script_exception","reason":"compile error","script_stack":["convertCurrency(/EUR/) * _value","                ^---- HERE"],"script":"convertCurrency(/EUR/) * _value","lang":"painless"}],"type":"search_phase_execution_exception","reason":"all shards failed","phase":"query","grouped":true,"failed_shards":[{"shard":0,"index":"03776182","node":"C4p_ha96QhK2uB47jV9pxg","reason":{"type":"script_exception","reason":"compile error","script_stack":["convertCurrency(/EUR/) * _value","                ^---- HERE"],"script":"convertCurrency(/EUR/) * _value","lang":"painless","caused_by":{"type":"illegal_state_exception","reason":"Regexes are disabled. Set [script.painless.regex.enabled] to [true] in elasticsearch.yaml to allow them. Be careful though, regexes break out of Painless's protection against deep recursion and long loops."}}}]},"status":500}`,
  toString: [Function],

At the same time normal expression are working well.

Upvotes: 1

Views: 637

Answers (1)

Val
Val

Reputation: 217474

You cannot invoke a JS callback from an ES script, it doesn't make sense as they don't execute in the same context.

What you should do is to first retrieve the EUR exchange rate in your Node.js code and then send your query with that exchange rate as a parameter to your script.

In pseudo code, it would look like this:

// 1. retrieve EUR/USD exchange rate
const EUR_USD = convertCurrency('EUR');

// 2. send your query
client.search({
  index : '03776182',
  body: {
    aggs : {
      price_ranges : {
          range : {
              field : "price",
              script : {
                 source : "params.rate * _value"
                 params: { 
                    rate: EUR_USD
                 }
              },
              ranges : [
                  { "from" : 10, "to" : 20 },
              ]
          }
      }
  }
  }

Upvotes: 1

Related Questions