用python进行弹性搜索部分更新

时间:2015-04-06 10:13:27

标签: python elasticsearch

我有以下格式的弹性搜索文档。我需要部分更新“x”字段并在其中添加python dict。

{
        "_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
                    ]
                }
            },
          }
        }

我尝试了以下代码进行更新:

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')

我收到此错误:

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

使用python在elasticsearch中进行部分更新的正确方法是什么?

2 个答案:

答案 0 :(得分:12)

为了将来参考,以下部分更新方法有效。

elasticsearch.update(index='gdata34', doc_type='gdat', id='328091-72341-7',
                     body={
                         'doc': {'x': {'y':'z'}}
                     }
                     )

答案 1 :(得分:1)

来自ElasticSearch docs on scripting

  

我们建议在应用程序或代理后面运行Elasticsearch,   它保护Elasticsearch免受外界影响。如果用户是   允许运行动态脚本(即使在搜索请求中),然后是它们   与Elasticsearch所用的用户具有相同的访问权限   跑来跑去。 因此,仅允许动态脚本   默认情况下使用沙盒语言。

现在,在最近的ES版本中,Groovy脚本引擎中的漏洞存在一个漏洞,它允许脚本在运行Elasticsearch Java VM时逃离沙箱并执行shell命令 - 这就是{的原因{ {3}},因此执行在请求正文或.scripts索引中传递的Groovy脚本。使用此默认配置执行Groovy脚本的唯一方法是将它们放在节点上的config/scripts/目录中。

所以你有两个选择:

  • 如果您的ES实例可直接访问并在代理后面受到保护,则可以通过在节点上的script.groovy.sandbox.enabled: true中设置config/elasticsearch.yml来再次打开Groovy沙盒(s )。如果您的ES实例可以通过
  • 访问
  • 您可以准备脚本并将其放在节点的config/scripts目录中的文件系统上,并按名称调用它。有关详细信息,请参阅Groovy sandbox is disabled by default in recent versions