【问题标题】:Individually update a large amount of documents with the Python DSL Elasticsearch UpdateByQuery使用 Python DSL Elasticsearch UpdateByQuery 单独更新大量文档
【发布时间】:2019-11-20 08:08:51
【问题描述】:

我正在尝试使用 UpdateByQuery 来更新大量文档的属性。但是由于每个文档都会有不同的值,所以我需要一个一个地执行 ir。我正在遍历大量文档,对于每个文档我都调用这个函数:

def update_references(self, query, script_source):

    try:
        ubq = UpdateByQuery(using=self.client, index=self.index).update_from_dict(query).script(source=script_source)
        ubq.execute()

    except Exception as err:
        return False

    return True

一些示例值是:

  • query = {'query': {'match': {'_id': 'VpKI1msBNuDimFsyxxm4'}}}
  • script_source = 'ctx._source.refs = [\'python\', \'java\']'

问题是,当我这样做时,我得到一个错误:“内部动态脚本编译过多,最大:[75/5m];请使用索引或带参数的脚本;此限制可以由[script.max_compilations_rate] 设置”。

如果我使用 Kibana 更改 max_compilations_rate,它没有效果:

PUT _cluster/settings
{
  "transient": {
    "script.max_compilations_rate": "1500/1m"
  }
}

无论如何,最好使用参数化脚本。我试过了:

def update_references(self, query, script_source, script_params):

    try:
        ubq = UpdateByQuery(using=self.client, index=self.index).update_from_dict(query).script(source=script_source, params=script_params)
        ubq.execute()

    except Exception as err:
        return False

    return True

所以,这次:

  • script_source = 'ctx._source.refs = params.value'
  • script_params = {'value': [\'python\', \'java\']}

但是由于我每次都要更新查询和参数,所以我需要为大集合中的每个文档创建一个新的 UpdateByQuery 实例,结果是同样的错误。

我还尝试使用以下方法遍历和更新大型集合:

es.update(
    index=kwargs["index"],
    doc_type="paper",
    id=paper["_id"],
    body={"doc": {
        "refs": paper["refs"]  # e.g. [\\'python\\', \\'java\\']
    }}
)

但我收到以下错误:“无法建立新连接:[Errno 99] 无法分配请求的地址 juil。10 18:07:14 bib gunicorn[20891]: POST http://localhost:9200/papers/paper/OZKI1msBNuDimFsy0SM9/_update [status:N /一个请求:0.005s"

所以,如果您对如何解决此问题有任何想法,我们将不胜感激。 最好的,

【问题讨论】:

  • 为什么不运行单个 UpdateByQuery 以匹配所有需要更新的文档,而不是运行一个每个 ID? UpdateByQuery-per-id 策略将比触发单个 UpdateByQuery 访问所有文档的速度慢几个数量级且成本更高。
  • 嗨@rusnyder,感谢您的反馈。你是对的,我将尝试为完整的文档集合创建一个脚本并迭代脚本中的值。我希望脚本没有限制:)我会让你知道它是怎么回事:)
  • @rusnyder 即使我一次处理 5 个文档,我也会得到“超过允许的最大内联脚本大小(以字节为单位)”:(
  • 知道了。如果您需要根据请求更新参数,那么我认为 UpdateByQuery 不是适合这项工作的工具。相反,我将遍历您需要更新的一组文档(就像您正在做的那样),为每个文档生成一个更新请求,然后使用Bulk API 分批提交它们。示例更新操作可能如下所示:{"update":{"_index":"...","_id":"abc123"}}\n{"doc":{"refs":["python","java"]}}(我正在使用部分文档更新,但如果需要,您可以使用脚本更新)
  • 谢谢!!我明天试试:)

标签: elasticsearch elasticsearch-dsl elasticsearch-dsl-py


【解决方案1】:

你可以这样试试。

PUT _cluster/settings
{
    "persistent" : {
        "script.max_compilations_rate" : "1500/1m"
    }
}

版本更新导致这些错误。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-03-22
    • 2017-01-02
    • 1970-01-01
    • 2018-10-13
    • 2016-08-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多