ElasticSearch:从存在的所有文档中删除字段(使用 Painless?)

pmi*_*hev 4 elasticsearch elasticsearch-painless

情况:我有一个严格映射的索引,我想从中删除一个不再使用的旧字段。因此,我使用不包含该字段的映射创建了一个新索引,并尝试将数据重新索引到新索引中。

问题:当我重新编制索引时,出现错误,因为我试图将数据索引到映射中不可用的字段中。所以为了解决这个问题,我想先从原始索引中的所有文档中删除该字段,然后才能重新索引。

PUT old_index/_doc/1
{
    "field_to_delete" : 5
}
PUT old_index/_doc/2
{
    "field_to_delete" : null
}
Run Code Online (Sandbox Code Playgroud)
POST _reindex
{
  "source": {
    "index": "old_index"
  },
  "dest": {
    "index": "new_index"
  }
}
Run Code Online (Sandbox Code Playgroud)
"reason": "mapping set to strict, dynamic introduction of [field_to_delete] within [new_index] is not allowed"
Run Code Online (Sandbox Code Playgroud)

1. 我发现的一些地方建议这样做:

POST old_index/_doc/_update_by_query
{
  "script": "ctx._source.remove('field_to_delete')",
  "query": {
    "bool": {
      "must": [
        {
          "exists": {
            "field": "field_to_delete"
          }
        }
      ]
    }
  }
}

Run Code Online (Sandbox Code Playgroud)

但是,这与具有显式值为 的文档不匹配null,因此在此更新后重新索引仍然失败。

2. 其他人(例如他们官方论坛上的 Elastic 团队成员)建议执行以下操作:

POST old_index/_doc/_update_by_query
{
  "script": {
    "source": """
          if (ctx._source.field_to_delete != null) {
            ctx._source.remove("field_to_delete");
          } else {
            ctx.op="noop";
          }
      """
    }
  },
  "query": {
    "match_all": {}
  }
}
Run Code Online (Sandbox Code Playgroud)

然而,这有同样的问题——它不会删除具有显式值的第二个文档null

3.最后我只能这样做:

POST old_index/_doc/_update_by_query
{
  "script": {
    "source": "ctx._source.remove("field_to_delete");"}
  },
  "query": {
    "match_all": {}
  }
}
Run Code Online (Sandbox Code Playgroud)

但这将更新所有文档,对于大型索引可能意味着部署期间的额外停机时间。

pmi*_*hev 6

最终我找到了正确的方法,所以我将它分享为一般知识:

POST old_index/_doc/_update_by_query
{
  "script": {
    "source": """
        if (ctx._source.containsKey("field_to_delete")) {
            ctx._source.remove("field_to_delete");
        } else {
          ctx.op="noop";
        }
      """
  },
  "query": {
    "match_all": {}
  }
}
Run Code Online (Sandbox Code Playgroud)