在 Elasticsearch 中,一个常见的问题是如何修改已存在的索引的字段类型。这是一个棘手的问题,因为 Elasticsearch 本身不允许直接修改字段类型。如果删除现有索引,重新建索引的话则会导致数据丢失。有一个方法是使用别名索引,当需要调整索引时可以先新建一个索引,把数据导入到新索引,之后将别名索引指向新索引。这些操作都是在es上完成,对于应用程序来说是无感知的。
以下是操作步骤:
假设有个索引product_statistic_spu,结构如下:
{
"mappings" : {
"properties" : {
"date" : {
"type" : "date"
},
"id" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"product_discount_rate" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"spu_code" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
}
}
}
}
现在需要将product_discount_rate字段的类型改成scaled_float, 新的索引结构如下:
{
"mappings" : {
"properties" : {
"date" : {
"type" : "date"
},
"id" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"product_discount_rate" : {
"type" : "scaled_float",
"scaling_factor" : 100.0
},
"spu_code" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
}
}
}
}
创建一个新的索引,我们称之为 “product_statistic_spu_alias”,并设置我们需要的新字段类型。
PUT product_statistic_spu_alias
{
"mappings" : {
"properties" : {
"date" : {
"type" : "date"
},
"id" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"product_discount_rate" : {
"type" : "scaled_float",
"scaling_factor" : 100.0
},
"spu_code" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
}
}
}
}
使用 _reindex
API 将 “product_statistic_spu” 索引的数据复制到 “product_statistic_spu_alias” 索引。
POST /_reindex
{
"source": {
"index": "product_statistic_spu"
},
"dest": {
"index": "product_statistic_spu_alias"
}
}
通过查询新索引的文档数量来确认数据已经完全复制过去。
GET product_statistic_spu/_count
GET product_statistic_spu_alias/_count
这里注意下,选一个不怎么写es实例的时间来做,或者说在这期间不要写es,保证两个数据一致。
在确认所有数据都已成功复制到新索引后,删除旧的 “product_statistic_spu” 索引。
DELETE /product_statistic_spu
为 “product_statistic_spu_alias” 索引创建一个别名 “product_statistic_spu”。这样,应用程序可以继续使用原始的索引名称进行操作,而实际上访问的是新创建的索引。
POST /_aliases
{
"actions": [
{
"add": {
"index": "product_statistic_spu_alias",
"alias": "product_statistic_spu"
}
}
]
}
在后续的使用中,如果需要更新 “product_statistic_spu” 索引,只需重复步骤1和2,创建一个新的索引,例如 “product_statistic_spu_alias_0515”,然后调整索引别名,使其指向新索引。
POST /_aliases
{
"actions": [
{
"remove": {
"index": "product_statistic_spu_alias",
"alias": "product_statistic_spu"
}
},
{
"add": {
"index": "product_statistic_spu_alias_0515",
"alias": "product_statistic_spu"
}
}
]
}
通过以上的操作我们实现了用别名来管理索引,在后续的维护中会方便很多。