【问题标题】:ElasticSearch: Delete field from all documents where it exists (with Painless?)ElasticSearch:从存在的所有文档中删除字段(使用 Painless?)
【发布时间】:2019-11-01 02:35:00
【问题描述】:

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

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

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

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

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

但是,这与具有显式值 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": {}
  }
}

但是,这有同样的问题 - 它不会删除具有显式值 null 的第二个文档。

3.最后我只能这样做:

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

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

【问题讨论】:

    标签: elasticsearch elasticsearch-painless


    【解决方案1】:

    最终我找到了正确的方法,所以我将其分享给大家:

    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": {}
      }
    }
    

    【讨论】:

    • 我本来建议使用containsKey,很好 ;-) ES 仍然需要遍历所有文档,但只有具有field_to_delete 的文档才会被有效更新。
    • 您应该使用存在查询而不是 match_all。然后您的脚本将仅在具有要删除的字段的文档上运行。见这里elastic.co/guide/en/elasticsearch/reference/current/…
    • @PierreMallet:不幸的是,这不起作用,因为查询不会返回带有"field_to_delete" : null 的文档并且它不会被更新
    • 哦,是的,你是对的:/你也许可以用一个明确的 null_value 来解决这个问题。见这里elastic.co/guide/en/elasticsearch/reference/current/…
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-05-03
    • 1970-01-01
    • 2013-07-07
    • 1970-01-01
    • 1970-01-01
    • 2021-12-04
    • 1970-01-01
    相关资源
    最近更新 更多