
A note for painless scripting
There are times when we use scripts, update data, scripted fields, and many more use cases. Prior to version 5.x, groovy was the default language for your scripts. We even did not specify which scripts we wanted to use back then. Since these scripts were executed remotely security was always a concern that Elastic Team had to address. This became the reason for designing Painless.
Painless is both secure and efficient when it comes to performance. It has a similar syntax as of Groovy so it is also easy to learn and use. For most of the cases, you don't need to make changes to your previously written scripts. All you need to add is a parameter called lang
and specify the value as painless
.
To define a variable in painless, simply use the following:
def myVar = 'my-value';
We don't need to specify any type. At runtime, the type of variable will be detected whatever suits appropriate. Painless supports all variable types defined by Java.
To define an array, use the following:
int[]
To define a list, use the following:
def nums = [1, 2, 3, 4, 5] nums[0] // 1st element nums[-1] // last element of the list
Similarly, map can also be defined:
def book = ['name': 'Java', 'pages': 450]; book.name // refers to Java
To loop through, use the following:
for(item:nums) { .. }
To further understand how to use this, we will use our index library, which has books. Let's consider that five pages are added to each book at the end for advertisement purposes. All the books in the library must be updated to add five more pages in the page count. To achieve this, we can use the update_by_query
endpoint from the Document API:
curl -XPOST "http://localhost:9200/library/book/_update_by_query" -d' { "script": { "inline": "ctx._source.pages += 5", "lang": "painless" }, "query": { "match_all": { } } }
In this simple example, we have just taken ctx._source
and updated the pages to add five pages for each book by querying using match_all
.
Let's add some more complexity to it. If all of the books had a publication field as well, similar to the book in the following document:
curl -XPUT "http://localhost:9200/library/book/41/_create?pretty" -d' { "author" : "Ravi Kumar Gupta", "title" : "Test-Driven JavaScript Development", "pages" : 240, "publication" : "packt" }'
Now, if we want to update pages by adding five more, but only for those books that were published by Packt, then we can use the following condition:
curl -XPOST "http://localhost:9200/library/book/_update_by_query" -d' { "script": { "inline": "if(ctx._source.publication == \"packt\"))" ctx._source.pages += 5", "lang": "painless" }, "query": { "match_all": { } } }'
Similarly, loop and other facilities provided by Painless can be utilized as script. A complete documentation for Painless scripting can be found at - https://www.elastic.co/guide/en/elasticsearch/reference/5.1/modules-scripting-painless.html.