0

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

StackOverflow 中有很多使用 python、curl 等来部分更新 ElasticSearch _source字段的示例。 elasticsearch python 库配备了一个elasticsearch.helpers文件夹,其中包含函数 - parallel_bulkstreaming_bulkbulk,允许开发人员轻松更新文档。

如果用户在 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的方法是什么?

4

2 回答 2

1

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

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

于 2022-01-10T07:14:45.217 回答
0

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

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 一起使用

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。

于 2022-01-27T06:57:31.680 回答