【问题标题】:Partially updating elasticsearch list field value using python使用python部分更新elasticsearch列表字段值
【发布时间】:2022-01-27 14:57:31
【问题描述】:

这个问题的目的是询问社区如何在不删除该字段的任何其他内容的情况下部分更新字段。

StackOverflow 中有很多示例使用 python、curl 等来部分更新 ElasticSearch _source 字段。elasticsearch python 库配备了一个 elasticsearch.helpers 文件夹,其中包含函数 - parallel_bulk、@987654323 @、bulk,方便开发者更新文档。

如果用户在 pandas 数据框中有数据,则可以轻松地遍历行以创建生成器,以在 elasticsearch 中更新/创建文档。 Elasticsearch 文档是不可变的,因此,当发生更新时,elasticsearch 将传递的信息用于创建新文档,增加文档版本,同时更新需要更新的内容。如果文档有一个字段作为列表,如果更新请求有一个值,它将替换整个列表为该新值。 (许多 SO QAs 涵盖了这一点)。 我不想用新值替换该列表的值,而是将列表中的单个值更新为新值。

例如,在我的 _source 中,我有一个字段为 ['101 country drive', '35 park drive', '277 Thunderroad belway']。该字段具有三个值,但假设我们意识到此文档不正确,我们需要将“101 country drive”更新为“1001 country drive”。

我不想删除列表中的其他值,而是用新值更新索引值。

我是否需要编写一个简单的脚本来执行此操作,或者是否有其他方法可以执行此操作?

示例: 想要更新文档 来自---

{'took': 176,
 'timed_out': False,
 '_shards': {'total': 1, 'successful': 1, 'skipped': 0, 'failed': 0},
 'hits': {'total': {'value': 0, 'relation': 'eq'},
  'max_score': None,
  'hits': [{'_index': 'docobot', '_type': '_doc', '_id': '19010239', 
'_source': {'name': 'josephine drwaler', 'address': ['101 country drive', '35 park drive', '277 thunderroad belway']
}}]}}

{'took': 176,
 'timed_out': False,
 '_shards': {'total': 1, 'successful': 1, 'skipped': 0, 'failed': 0},
 'hits': {'total': {'value': 0, 'relation': 'eq'},
  'max_score': None,
  'hits': [{'_index': 'docobot', '_type': '_doc', '_id': '19010239', 
'_source': {'name': 'josephine drwaler', 'address': ['1001 country drive', '35 park drive', '277 thunderroad belway']
}}]}}

请注意,地址仅针对第一个索引进行更新,但索引号不应成为更新_source中地址值的因素。

在弹性搜索中部分更新文档同时保持该字段中剩余值的完整性的最有效和 Pythonic 方法是什么?

【问题讨论】:

    标签: elasticsearch elasticsearch-painless elasticsearch-py elasticsearch-scripting elasticsearch-bulk


    【解决方案1】:

    _source 是在 API 请求中传递给 Elasticsearch 的内容,它不是与 address 相同的上下文中的“字段”

    也就是说,您需要将整个 address 字段替换为您想要的,而不仅仅是您想要更正的值。 Elasticsearch 假定您传入的是整个字段的值应该是什么,并将用它得到的内容覆盖该字段

    【讨论】:

      【解决方案2】:

      需要创建一个无痛的脚本来更新。这样做时需要记住,您可以通过以下方式访问源中的任何字段:

      ctx._source.address = ['1001 country drive', '35 park drive', '277 thunderroad belway']
      

      但这并不能解决问题...

      该字段是一个列表,因此我们需要遍历该列表。下面的无痛脚本循环遍历每个项目,将其与搜索参数进行比较,如果匹配则返回答案。

      def upd_address= [];
      for (def item: ctx._source.address) ]
      { 
        if (item == params.search_id) {
         upd_address.add(params.answer)
          } 
        else {
         upd_address.add(item)
       }} ctx._source.address = upd_address; 
      

      您可以将上述内容与 elasticsearch_dsl as 一起使用

      ubq = UpdateByQuery(using=[your es connection], doc_type='doc', index=['your index']
      ubq = ubq.script(source=[above query], params={'search_id': addrss, 'answer': upd_addrss)
      res = ubq.execute()
      print(res, type(res))
      

      更新查询循环遍历列表中的每个项目。检查项目是否是搜索 id,如果是则保留答案,否则保持相同的 id。

      【讨论】:

        猜你喜欢
        • 2019-01-25
        • 2020-07-04
        • 2021-12-04
        • 1970-01-01
        • 2018-02-11
        • 2021-03-14
        • 2018-05-25
        • 1970-01-01
        • 2023-03-19
        相关资源
        最近更新 更多