重新索引数据

虽然你可以给索引添加新的类型,或给类型添加新的字段,但是你不能添加新的分析器或修改已有字段。假如你这样做,已被索引的数据会变得不正确而你的搜索也不会正常工作。

修改在已存在的数据最简单的方法是重新索引:创建一个新配置好的索引,然后将所有的文档从旧的索引复制到新的上。

_source 字段的一个最大的好处是你已经在Elasticsearch中有了完整的文档,你不再需要从数据库中重建你的索引,这样通常会比较慢。

为了更高效的索引旧索引中的文档,使用【scan-scoll】来批量读取旧索引的文档,然后将通过【bulk API】来将他们推送给新的索引。

批量重新索引:

你可以在同一时间执行多个重新索引的任务,但是你显然不愿意他们的结果有重叠。所以,可以将重建大索引的任务通过日期或时间戳字段拆分成较小的任务:

GET /old_index/_search?search_type=scan&scroll=1m
{
"query" : {
"range" : {
"date" : {
"gte" : "2014-01-01",
"lt" : "2014-02-01"
}
}
},
"size" : 1000
}

假如你继续在旧索引上做修改,你可能像确保新增的文档被加到了新的索引中。这可以通过重新运行重建索引程序来完成,但是记得只要过滤出上次执行后新增的文档就行了。

索引别名和零停机时间

前面提到的重新索引过程中的问题是必须更新你的应用,来使用另一个索引名。索引别名正是用来解决这个问题的!

索引别名就像一个快捷方式或软连接,可以指向一个或多个索引,也可以给任何需要索引名的API使用。别名带给我们极大地灵活性,允许我们做到:

  • 在一个运行的集群上无缝的从一个索引切换到另一个
  • 给多个索引分类(例如, last_three_months)
  • 给索引的一个子集创建 视图

这里有两种管理别名的途径: _alias 用于单个操作, _aliases 用于原子化多个操作。


我们假设采用一个叫my_index的索引。而事实上,my_index 是一个指向当前真实索引的别名。真实的索引名将包含一个版本号: my_index_v1,my_index_v2等等。


开始,我们创建一个索引 my_index_v1,然后将别名my_index指向他:


PUT /my_index_v1


PUT /my_index_v1/_alias/my_index


创建索引 my_index_v1


将别名my_index指向 my_index_v1.


你可以检测这个别名指向哪个索引:


GET /*/_alias/my_index


或哪些别名指向这个索引:


GET /my_index_v1/_alias/*


两者都将返回下列值:


update 加索引 更新索引字段_索引


然后,我们决定修改索引中一个字段的映射。当然我们不能修改现存的映射,索引我们需要重新索引数据。首先,我们创建有新的映射的索引my_index_v2.


PUT /my_index_v2 

 
{ 

 
"mappings" : { 

 
"my_type" : { 

 
"properties" : { 

 
 
 
 
"tags" : { 

 
"type" : "string", 

 
"index" : "not_analyzed" 

 
} 

 
} 

 
} 

 
} 

 
}


然后我们将数据从my_index_v1 迁移到 my_index_v2。一旦我们认为数据已经被正确的索引了,我们就将别名指向新的索引。


别名可以指向多个索引,所以我们需要在新索引中添加别名的同时从旧索引中删除它。这个操作需要原子化,所以我们需要用 _aliases 操作:


POST /_aliases 

 
{ 

 
"actions" : [ 

 
{ "remove" : { "index" : "my_index_v1" , "alias" : "my_index" } }, 

 
{ "add" : { "index" : "my_index_v2" , "alias" : "my_index" } } 

 
] 

 
}


这样,你的应用就从旧索引迁移到新的,而没有停机时间。


提示:


即使你认为现在的索引设计已经是完美了,当你的应用在生产环境使用时,还是有可能在今后有一些改变的。


所以请做好准备:在应用中使用别名而不是索引。然后你就可以在任何时候重建索引。别名的开销很小,应当广泛使用。