Use the Scripting Module to Update a Document in Elasticsearch

Have a Database Problem? Speak with an Expert for Free
Get Started >>

Introduction

Scripting is usually performed with Painless or Java and can be used to create scripts that will update Elasticsearch documents with customized expressions. Previously, Groovy, a scripting language that used Java syntax was the default language, however, this has been depreciated since Elasticsearch version 5.x was released.

Painless is a faster, safer and simpler than using other scripting languages in Elasticsearch and has a Java-like syntax, similar to Groovy.

Painless is a scripting language designed specifically for both performance and security. While the Painless syntax is similar to Java’s, it has a number of additional features, like array initializers, dynamic typing and map and list-access shortcuts. Elasticsearch users can quickly perform a variety of operations by enabling the script modules. The scripts can be used to execute a wide range of tasks, such as modifying specific elements in a field and returning specific fields in a search request. The scripting module also allows you to employ scripts to assess custom expressions. For example, you can use a script to generate a script field as part of a search query and evaluate a custom score for a specific query.

Prerequisites

  • Java 8 and Elasticsearch must be installed and running on your server in order for the Scripting module to function properly. Navigate to https://{YOUR_SERVER}.com:9200 or http://localhost:9200 in your browser or use the following cURL request to see if Elasticsearch is running:
1
curl -X GET localhost:9200

A screenshot image of a cURL request made using a UNIX terminal that uses information on an Elasticsearch cluster running on a specific server * If you are planning to make scripting requests using Kibana’s Console UI, then check to make certain the Kibana service is running on your server (5601 is the default port for Kibana).

  • You must be able to read, write and fully comprehend the syntax of the Painless and Java languages.

NOTE: If you’re using Elasticsearch version 5.x or later, make certain all scripting requests that are made in cURL define the request body’s content type as a header option by including: -H 'Content-Type: application/json' in the header, or you will receive a 406 Content-Type error:

How to use scripts in Elasticsearch

  • Scripting is a more efficient way to execute a variety of tasks with only one request by adding a string with a series of commands written in a scripting language.
  • The scripting modules allows you to carry out a variety of operations, such as finding certain fields of a document in a search query or changing the values of fields in documents.

  • The “script” field is the section of the request that comprises the “body” of the scripting request.

The body of a Scripting Module request has several essential components:

1
2
3
4
5
6
7
8
9
10
11
12
# the "script" field encompasses the main body of the JSON scripting request
"script": {

# scripting language name
"lang": "painless",

# source object (or document ID) as well as the operations performed by the script
"source": "ctx._source = params.someNum",

# the parameters or values for the script's operations
"params": { "someNum = 12345" }
}

DO NOT include the commented lines with the # when making theses types of requests in Kibana or when using cURL.

For more information you should consult Elastic’s full documentation on the Scripting Processor.

“lang”: The scripting language field:

  • Insert the name of the scripting language used into this field’s value.
  • Preveously, Groovy was Elastic’s default scripting language, but was replaced by Painless in Elasticsearch v5.x and later versions.

"source": The source object and ctx variable:

  • Make certain to specify the intended operations for the ctx object in the "source" field whenever you submit a script request. The values in this field are essentially used to describe what the script request will do.
  • To access the source of an Elasticsearch document using the ctx variable, use _source as in ctx._source.
  • It’s also permitted to simply pass the Elasticsearch document’s ID as the source.

NOTE: The ctx variable is a unique “stand-in” of the document or object being modified or inspected. As such, any changes made to the ctx object passed in the "source" field will persist after the script has performed its operations.

“param”: The script’s parameters:

  • The values passed in the "params" field are used for the script’s parameters, meaning the value or expression for the operations passed in the "source" field of the JSON object.
  • If the "source" field is used for passing operations, and the object has operations performed on it, then the "param" field is how you specify to what extent those operations are performed on the source.

Using Painless scripting to make a _search request in Elasticsearch

  • Here is an example of a GET request used to perform a _search operation using Painless scripting language:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
GET my_index/_search
{
"script_fields": {
"some_field": {
"script": { # the body of the script
"lang": "painless",
"source": "doc['some_field'] * params.meaningOfLife",
"params": {
"meaningOfLife": 42
}
}
}
}
}

In this example, the script will return all Elasticsearch documents having an integer value of 42 within a specific field named "some_field".

Using Painless Scripting to Update an Elasticsearch Document

  • Here is an example of how to execute a Painless script. This example will change the "color" field’s value to "grey" for document number 1 in the "cars index:
1
2
3
4
5
6
7
8
9
10
POST cars/volvo/1/_update
{
"script" : {
"source": "ctx._source.color = params.tag",
"lang": "painless",
"params" : {
"tag" : "grey" # params.tag
}
}
}

Note how .tag is passed as an attribute of the "params" field in the "source" field’s string value.

  • Here is POST call for the same request to update a document’s "color" using cURL:
1
2
3
4
5
6
7
8
9
10
11
curl -X POST "localhost:9200/cars/volvo/1/_update" -H 'Content-Type: application/json' -d'
{
"script" : {
"source": "ctx._source.color = params.tag",
"lang": "painless",
"params" : {
"tag" : "grey"
}
}
}
'

How to Add and Remove Fields in an Elasticsearch Document using Painless Scripting

  • You are also able to add and delete the "_source" fields in an Elasticsearch document with the scripting module.

Add a new "_source" field using a Painless script:

Here is an example of a simple _update request that uses Painless scripting to produce a new field for a document in the cars index:

1
2
3
4
POST cars/volvo/1/_update
{
"script" : "ctx._source.year = '2014'"
}

The cURL version of the _update request:

1
2
3
4
5
curl -X POST "localhost:9200/newcar/volvo/1/_update" -H 'Content-Type: application/json' -d'
{
"script" : "ctx._source.year = '
2014'"
}
'

Update an Elasticsearch Document using Painless Scripting in Kibana’s Console UI:

A screenshot of a POST request in Kibana to update an Elasticsearch document using Painless scripting

  • You should see a JSON response, with a "result" status of "updated", in Kibana’s output pane on the right-hand side of the screen:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
{
"_index" : "cars",
"_type" : "volvo",
"_id" : "1",
"_version" : 2,
"result" : "updated",
"_shards" : {
"total" : 2,
"successful" : 1,
"failed" : 0
},
"_seq_no" : 2,
"_primary_term" : 1
}

  • You can, and should, verify the update was successful by making a new GET request in Kibana:
1
GET cars/volvo/1

Alternatively, you can use cURL in a terminal to obtain the JSON response of the document:

1
curl -X GET "localhost:9200/cars/volvo/1?pretty"
  • The JSON response for the GET request should look like this in both Kibana and in a terminal using cURL:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{
"_index" : "cars",
"_type" : "volvo",
"_id" : "1",
"_version" : 2,
"_seq_no" : 2,
"_primary_term" : 1,
"found" : true,
"_source" : {
"color" : "red",
"engine" : "v6",
"model" : "V50 Wagon",
"year" : "2014"
}
}

How to Remove a "_Source" Field using a Painless Script:

  • You can also remove a document’s field using the Update API and a simple Painless script.
  • The following HTTP request will remove the previously-added field:
1
2
3
4
POST newcar/volvo/1/_update
{
"script" : "ctx._source.remove('year')"
}

Conclusion

In this tutorial you learned how easy it is to use the scripting module to change or update a document in Elasticsearch. You learned the basic Elasticsearch scripting concepts, ways to invoke scripts, the languages that scripts can be written in and some basic scripting examples.

Remember that Painless is the default scripting language and was designed specifically for use with Elasticsearch. Painless scripts run faster and are safer than alternatives and extends the Java syntax with a subset of Groovy. The Painless scripting module can safely be used anywhere that scripts can be utilized in Elasticsearch. Once you have learned the basic concepts of using the scripting module to update a document you will be able to move on to more advance functions.

Pilot the ObjectRocket Platform Free!

Try Fully-Managed CockroachDB, Elasticsearch, MongoDB, PostgreSQL (Beta) or Redis.

Get Started

Keep in the know!

Subscribe to our emails and we’ll let you know what’s going on at ObjectRocket. We hate spam and make it easy to unsubscribe.