【问题标题】:Elasticsearch inline string replace seems to do nothingElasticsearch 内联字符串替换似乎什么都不做
【发布时间】:2021-06-07 23:35:38
【问题描述】:

我们在弹性搜索索引中有一些遗留字段,这给我们带来了一些麻烦,我们想对整个索引执行字符串替换。

例如,一些旧时间戳以2000-01-01T00:00:00.000+0100 的格式存储,但应存储为2000-01-01T00:00:00.000+01:00

我尝试运行以下查询:

POST /my_index/_update_by_query
{
    "script":
    {
        "lang": "painless",
        "inline": "ctx._source.timestamp = ctx._source.timestamp.replace('+0100', '+01:00')"
    }
}

我在 Kibana 中运行查询,但我总是遇到查询超时 - 我想这不一定是坏事,因为数据库很大,但是我从来没有看到更新的字段。

有没有办法查看此类查询的状态?

我也尝试为更新创建搜索查询,但没有成功:

GET /my_index/_search
{
  "query": {
    "query_string": {
      "query": "*0100",
      "allow_leading_wildcard": true,
      "analyze_wildcard": true,
      "fields": ["timestamp"]
    }
  }
}

不幸的是,它总是返回空集 - 不确定可能出了什么问题。

实现此类更新的正确方法是什么?

【问题讨论】:

  • 你应该使用wait_for_completion=false参数在后台运行任务,见here how
  • 听起来很有帮助!您还可以检查搜索查询吗?为什么它不会返回任何结果?
  • 日期字段不像文本字段那样分析,所以这就是这种查询(即通配符查询)有效的原因
  • 顺便说一句,您的映射对于该字段的外观如何?
  • 为什么说“破”?如果提取的文档没有错误,则表示该值符合预期的日期格式,即+0100+01:00 相同,两者都是 GMT+1 时区的有效语法

标签: elasticsearch elasticsearch-painless


【解决方案1】:

我会使用 ingest pipeline 来解决这个问题,您将使用它来更新整个索引。

首先,创建如下所示的摄取管道。它的作用是检测具有以+0100 结尾的timestamp 字段的文档,然后更新时间戳以使用正确格式的时区。

PUT _ingest/pipeline/fix-tz
{
  "processors": [
    {
      "dissect": {
        "if": "ctx.timestamp.endsWith('+0100')",
        "field": "timestamp",
        "pattern": "%{timestamp}+%{tz}"
      }
    },
    {
      "set": {
        "if": "ctx.tz != null",
        "field": "timestamp",
        "value": "{{timestamp}}+01:00"
      }
    },
    {
      "remove": {
        "if": "ctx.tz!= null",
        "field": "tz"
      }
    }
  ]
}

然后,当管道被创建时,你只需要用它来更新你的索引,就像这样:

POST my_index/_update_by_query?pipeline=fix-tz&wait_for_completion=false

一旦完全运行,您的索引应该会正确更新。

【讨论】:

  • 您能否解释一下如何对此类字段执行类似GET /my_index/_search 的查询?
  • 这不可能。有一个 script 查询,但出于性能原因,它不允许您从 ctx._source 检索原始字符串
猜你喜欢
  • 2022-01-14
  • 2015-10-29
  • 2012-09-12
  • 2011-03-17
  • 2017-09-11
  • 2021-05-30
  • 2013-05-31
  • 2013-05-31
  • 2016-09-22
相关资源
最近更新 更多