Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Elastic Search: How to write multi statement scripts?

I have values stored on a document in an Elasticsearch index.
I need to do some date manipulation on the values and return a boolean value to be used in a filter.
The script covers several lines, and I can't get it to run.

I've written other single scripts that work fine, however I know less than nothing about Groovy and very little about Elastic search.

Each and every sample I can find with a script has one line and only one line.

So basically how would I take this perfectly valid script

"script": {
    "script": "doc['state'].value == 'completed' && doc['lastStateUpdate'].value < doc['dueDate'].value"
    }

And turn it into some thing like

"script": {
    "script": "def isCompleted = doc['state'].value == 'completed' 
               def preSLA = doc['lastStateUpdate'].value < doc['dueDate'].value
               return isCompleted && preSLA"
    }

I'm not mad about the idea of creating a write-only one liner that expresses the logic, I can see more of these coming down the line and while this one is relatively straight-forward, a "one liner" isn't going to cut it.

The alternative here is to do some preprocessing on the document before it's indexed, and add extra data to it. However this has drawbacks in that it's rather inflexible and we'd need to reindex all the data to change these aggregations, which we'd rather not do.

like image 599
Binary Worrier Avatar asked Nov 02 '15 14:11

Binary Worrier


People also ask

How do you write an elastic search script?

Wherever scripting is supported in the Elasticsearch APIs, the syntax follows the same pattern; you specify the language of your script, provide the script logic (or source), and add parameters that are passed into the script: "script": { "lang": "...", "source" | "id": "...", "params": { ... } }

What is CTX in Elasticsearch?

ctx is a special variable that allows you to access the source of the object that you want to update. The ctx. _source is a writable version of the source . NOTE: You can modify this document in the script and the modified source will be persisted as the new version of the document.

What is Msearch?

mSearches Startpage is a potentially unwanted application (PUA), a browser hijacker which promotes msearches.com, the address of a fake search engine. Generally, browser hijackers change certain browser settings to the promoted URL.

What is painless script in Elasticsearch?

Painless is a simple, secure scripting language designed specifically for use with Elasticsearch. It is the default scripting language for Elasticsearch and can safely be used for inline and stored scripts.


2 Answers

If you want to break your script into multiple lines you have to surrond your script with """ docs

`"query": {
    "function_score": {
      "script_score": {
        "script": {
          "lang": "painless",
          "source": """
            int total = 0;
            for (int i = 0; i < doc['goals'].length; ++i) {
              total += doc['goals'][i];
            }
            return total;
          """
        }
      }
    }
  }
}`

Update: For some versions of Elasticsearch source should be replaced with inline docs

like image 53
Ivan Ruski Avatar answered Nov 04 '22 04:11

Ivan Ruski


You simply need to separate each statement with a semicolon:

"script": {
    "script": "isCompleted = doc['state'].value == 'completed'; preSLA = doc['lastStateUpdate'].value < doc['dueDate'].value; return isCompleted && preSLA;"
    }

Make sure to not add line breaks inside your script string, though, as it would not be valid JSON.

like image 34
Val Avatar answered Nov 04 '22 04:11

Val