12

I have a elasticsearch document in the following format. I need to partial update the "x" field and add a python dict in it.

{
        "_index": "gdata34",
        "_type": "gdat",
        "_id": "328091-72341-118",
        "_version": 1,
        "_score": 1,
        "_source": {
            "d": {
                "Thursday": {
                    "s": ""
                },
                "Email": {
                    "s": ""
                },
               "Country": {
                    "s": "US"
                },

            },
            "x": {
                "Geo": {
                    "s": "45.335428,-118.057133",
                    "g": [
                        -118.057133
                        ,
                        45.335428
                    ]
                }
            },
          }
        }

I tried the following code to update:

from elasticsearch import Elasticsearch, exceptions
import pprint


elasticsearch = Elasticsearch()
doc = elasticsearch.get(index='gdata34', doc_type='gdat', id='328091-72341-7')

elasticsearch.update(index='gdata34', doc_type='gdat', id='328091-72341-7',
                     body={"script":"ctx._source.x += y",
                           "params":{"y":"z"}
                     }
                     )
elasticsearch.indices.refresh(index='gdata34')
new_doc = elasticsearch.get(index='gdata34', doc_type='gdat', id='328091-72341-7')

I am getting this error:

elasticsearch.exceptions.RequestError: TransportError(400, u'ElasticsearchIllegalArgumentException[failed to execute script]; nested: ScriptException[dynamic scripting for [groovy] disabled]; ')

What is the right way to do partial update in elasticsearch using python?

1
  • What version of ES are you using? Commented Apr 6, 2015 at 10:42

2 Answers 2

13

For future reference, the following method of partial update worked.

elasticsearch.update(index='gdata34', doc_type='gdat', id='328091-72341-7',
                     body={
                         'doc': {'x': {'y':'z'}}
                     }
                     )
Sign up to request clarification or add additional context in comments.

Comments

1

From the ElasticSearch docs on scripting:

We recommend running Elasticsearch behind an application or proxy, which protects Elasticsearch from the outside world. If users are allowed to run dynamic scripts (even in a search request), then they have the same access to your box as the user that Elasticsearch is running as. For this reason dynamic scripting is allowed only for sandboxed languages by default.

Now, in recent ES version there has been a bug in the vulnerability in the Groovy scripting engine that allows scripts to escape the sandbox and execute shell commands as the user running the Elasticsearch Java VM - that's why the Groovy sandbox is disabled by default in recent versions, and therefore the execution of Groovy scripts passed in the request body or from the .scripts index. The only way to execute Groovy scripts with this default configuration is to place them in the config/scripts/ directory on the node.

So you have two options:

  • If your ES instance is not directly accessible and is secured behind a proxy, you can turn on Groovy sandboxing again by setting script.groovy.sandbox.enabled: true in config/elasticsearch.yml on your node(s). If your ES instance is accessible by your
  • You can prepare your script and place it on the filesystem in the config/scripts directory of your node(s), and call it by name. See Running Groovy Scripts without Dynamic Scripting for details.

3 Comments

can we use the following?elasticsearch.update(index='gdata34', doc_type='gdat', id='328091-72341-7', body={ 'doc': {'x': {'y':'z'}} } )
Yes, but make sure to read the documentation - unless you specify "detect_noop": true this will always result in the document being updated, even if the merging process didn't detect any changes.
At least with ElasticSearch 2.3 (the latest version at this time), detect_noop is enabled by default.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.