如何在Elasticsearch中真正重新索引数据

40

我已添加了新的映射(主要是现有字段的not_analyzed版本),现在我需要找出如何重新索引现有数据。我尝试了遵循elastic search网站上的指南,但那太令人困惑了。我还尝试使用插件(elasticsearch-reindex、allegro/elasticsearch-reindex-tool)。 我看过ElasticSearch - Reindexing your data with zero downtime ,这是一个类似的问题。我希望不必依赖外部工具(如果可能的话),并尝试使用bulk API(与原始插入一样)。

由于它是只读数据,我可以很容易地重建整个索引,但如果我在实际生产中需要添加更多字段等等,那么这不会长期有效。我想知道是否有人知道ES的易于理解/遵循的解决方案或步骤,适用于相对初学者。我使用Windows,版本为2。


你使用的是哪个版本的ElasticSearch?如果你使用的是2.3版本,那么本地的_reindex api是可用的。它可以精确地完成你所需要的操作。我不确定你指的是哪个指南(“elastic search网站上的指南”),但这是关于reindex api的文档:https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-reindex.html如果我没记错的话,你可以将索引重新编制到同一个索引中,从而有效地保留数据。但是你必须注意文档版本问题。 - Jeff Gandt
是的,几个月前我也遇到了这个问题,但我也注意到了重新索引API的可用性...无法验证是否可以将索引重新索引到同一索引中。 - metase
1
似乎您无法将索引重新索引到同一索引中。 - metase
我有同样的问题。您可以查看这个答案 - NatsuDragonEye
这里是一个在现有索引上创建新映射的小流程(带重新索引):https://codeburst.io/modify-elasticsearch-mappings-and-settings-without-downtime-223911c0e521 - rap-2-h
5个回答

26
重新索引意味着读取数据,删除elasticsearch中的数据并再次摄取数据。不存在“直接更改现有数据映射”的情况。您提到的所有重新索引工具都只是围绕读取-删除-摄取的包装器。
您始终可以调整新索引的映射并稍后添加字段。所有新字段将根据此映射进行索引。或者,如果您无法控制新字段,则使用动态映射。
请查看Change default mapping of string to "not analyzed" in Elasticsearch以了解如何使用动态映射获取字符串的not_analyzed字段。

重新索引非常昂贵。更好的方法是创建一个新索引并删除旧索引。为了在零停机时间下实现这一点,请为所有客户使用索引别名。考虑一个名为"data-version1"的索引。步骤如下:

  • 创建名为"data-version1"的索引,并给它一个名为"data"的别名。
  • 在所有客户端应用程序中只使用别名"data"。
  • 要更新映射:创建一个名为"data-version2"的新索引(具有新映射),并将所有数据放入其中(您可以使用_reindex API来完成)。
  • 切换从version1到version2:在version1上删除别名"data",在version2上创建别名"data"(或先创建,然后再删除)。这两个步骤之间的时间内,您的客户端将没有(或者是双倍的)数据。但删除和创建别名之间的时间应该很短,以至于您的客户端不应该注意到。

始终使用别名是一个好习惯。


谢谢回复。我想更倾向于“零停机”方法。我可以再次推入另一个数据集,这将需要15-20分钟,并使用包含分析和未分析字段的新映射版本。(这是备用计划)。实际上,当我处于生产状态时,我想探索不必这样做的其他选项。 - metase
如果您创建了一个新的索引,那么您只能添加一个新的映射 - 抱歉我的帖子没有表述清楚。我已经在上面添加了这个信息。大多数用户为每个时间段(比如每天)拥有单独的索引。然后,所有新创建的索引都会应用新的字段和/或新的映射。我在帖子中还提到了零停机时间的一些想法。 - dtrv
@dtrv 你知道如果在重新索引命令运行时,客户端将新数据索引到“data-version1”会发生什么吗?它也会被捕捉到吗? - cah1r
@cah1r 客户端应该使用别名"data"而不是索引"version1"。如果只有一个索引具有该别名,则可以对别名进行索引。这样,新数据被索引到"version1"之前的别名切换中,并在之后索引到"version2"中。您还可以将索引设置为只读,以避免在重新索引过程开始后添加新数据。 - dtrv
@drtv 好的 :) 但问题仍然存在。您提到使用Reindexing API来迁移数据。假设您运行该命令,有1000万个文档需要迁移。操作将持续15分钟。如果在这15分钟内向第一个索引添加了100个新文档,您知道正在进行的Reindexing操作是否会捕获它们吗?因此,在version2中,我们应该有1000万和100个文档。通常在切换后,我们不希望丢失任何数据。 - cah1r
显示剩余2条评论

15

从2.3.4版本开始,新的api _reindex可用,它将完全做到其所说的。基本用法如下:

_reindex 是一个新的API,用于重新索引数据。

{
    "source": {
        "index": "currentIndex"
    },
    "dest": {
        "index": "newIndex"
    }
}

1
你可以从“currentIndex”重新索引到一个临时索引,然后再返回到“currentIndex”。您可以使用op_type和version_type参数来控制如何处理重复/覆盖数据。 - Jeff Gandt
那就是我最终做的。 - metase

5
如果您像我一样想要一个直接的答案来解决这个常见而基础的问题,这个问题通常被Elastic和社区忽视了,以下是对我有效的代码。
假设您只是在调试而不是在生产环境中,并且可以绝对合法地添加或删除字段,因为您绝对不关心停机时间或延迟:
# First of all: enable blocks write to enable clonage
PUT /my_index/_settings
{
  "settings": {
    "index.blocks.write": true
  }
}

# clone index into a temporary index
POST /my_index/_clone/my_index-000001  

# Copy back all documents in the original index to force their reindexetion
POST /_reindex
{
  "source": {
    "index": "my_index-000001"
  },
  "dest": {
    "index": "my_index"
  }
}

# Disable blocks write
PUT /my_index/_settings
{
  "settings": {
    "index.blocks.write": false
  }
}

# Finaly delete the temporary index
DELETE my_index-000001

在将所有文档从原始索引复制过来时,sourcedest中是否存在拼写错误(应该是反过来的)? - undefined

2

2020年1月更新:Elasticsearch从远程主机重新索引到本地主机示例

# show indices on this host
curl 'localhost:9200/_cat/indices?v'

# edit elasticsearch configuration file to allow remote indexing
sudo vi /etc/elasticsearch/elasticsearch.yml

## copy the line below somewhere in the file
>>>
# --- whitelist for remote indexing ---
reindex.remote.whitelist: my-remote-machine.my-domain.com:9200
<<<

# restart elaticsearch service
sudo systemctl restart elasticsearch

# run reindex from remote machine to copy the index named filebeat-2016.12.01
curl -H 'Content-Type: application/json' -X POST 127.0.0.1:9200/_reindex?pretty -d'{
  "source": {
    "remote": {
      "host": "http://my-remote-machine.my-domain.com:9200"
    },
    "index": "filebeat-2016.12.01"
  },
  "dest": {
    "index": "filebeat-2016.12.01"
  }
}'

# verify index has been copied
curl 'localhost:9200/_cat/indices?v'

0

我也遇到了同样的问题。但是我找不到任何资源来更新当前索引映射和分析器。我的建议是使用滚动和扫描API,并将您的数据重新索引到具有新映射和新字段的新索引中。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接