如何在 ElasticSearch 索引期间从现有字段创建新字段?

时间:2021-01-26 09:26:23

标签: elasticsearch

我有一个从 Kinesis 接收事件并将事件写入 ElasticSearch 集群的 Lambda。

<头>
文档编号 第一个时间戳
d1 15974343498

现在当我们收到另一个事件时,我想将 ElasticSearch 中的文档更新为

<头>
文档编号 第一个时间戳 第二个时间戳 时间标签
d1 15974343498 15974344498 1000

如何在不必先从 ElasticSearch 获取现有文档然后执行 PUT 的情况下执行此操作?

我找到了更新选项 here,我可以使用它添加字段 SecondTimestamp,但是如何添加 TimeTag 字段;它要求我们使用 FirstTimestamp 进行操作。

1 个答案:

答案 0 :(得分:1)

不需要 GET 操作。

根据您配置写入方式的难易程度,您可以执行以下操作:

  1. 将需要更新文档内容的脚本存储为 params
POST _scripts/manage_time_tags
{
  "script": {
    "lang": "painless", 
    "source": """
      if (ctx._source.FirstTimestamp != null && params.FirstTimestamp != null) {
        ctx._source.SecondTimestamp = params.FirstTimestamp;
        ctx._source.TimeTag = ctx._source.SecondTimestamp - ctx._source.FirstTimestamp;
      }
    """
  }
}
  1. 不要像之前那样直接写入 ES,而是使用 Update API 的 upsert 方法:
POST myindex/_update/1
{
  "upsert": {
    "id": 1,
    "FirstTimestamp": 15974343498
  },
  "script": {
    "id": "manage_time_tags",
    "params": {
      "id": 1,
      "FirstTimestamp": 15974343498
    }
  }
}

这将确保如果文档尚不存在,upsert 的内容会被同步并且脚本甚至不会运行。

  1. 随着新事件的出现,只需再次调用 /_update/your_id,但使用idFirstTimestamp最新内容
POST myindex/_update/1
{
  "upsert": {
    "id": 1,
    "FirstTimestamp": 15974344498         
  },
  "script": {
    "id": "manage_time_tags",
    "params": {
      "id": 1,
      "FirstTimestamp": 15974344498
    }
  }
}

注意:这不应与名称相当糟糕的 scripted upsert 混淆,后者将运行脚本,而不管文档是否已经存在。应省略此选项(或设置为 false)。