- 1. 使用场景
- 2. 案例1:为索引增加子字段
- 写入文档
- 查看 Mapping
- 查询 Mapping 变更前写入的文档
- 写入文档
- 查询新写入文档
- 3. 案例2:更改已有字段类型的 Mappings
- 查看 Mapping
- 修改keyword字段的类型 text->keyword
- 1) op_type:create
- 2) version_type
- Reindx API
- Reindx API,version Type Internal,目标索引中已经存在相同id的文档
- 不管目标索引中_version是多少,根据源索引中文档版本号增加,文档version: 1->2
- Reindx API,version Type External,目标索引中已经存在相同id的文档
- 如果目标索引中 _version=2,只有源索引中 _version>2 才能迁移并更新成功,如:源 _version=5,否则报错
1. 使用场景
一般以下几种情况时,需要重建索引:
- 索引的 Mapping 发生变更:字段类型更改,分词器、字典更新
- 索引的 Settings 发生变更:索引的主分片数发生改变
- 集群内,集群间需要做数据迁移
Elasticsearch 的内置提供的 API
- Update By Query:在现有索引上重建
- ReIndex:在其他索引上重建索引
2. 案例1:为索引增加子字段
- 写入文档,并查看 Mapping
查看 Mapping
GET blogs/_mapping
### Mapping配置
{ “blogs” : { “mappings” : { “properties” : { “content” : { “type” : “text”, “fields” : { “keyword” : { “type” : “keyword”, “ignore_above” : 256 } } }, “keyword” : { “type” : “text”, “fields” : { “keyword” : { “type” : “keyword”, “ignore_above” : 256 } } } } } } }
- 改变 Mapping,增加子字段,使用英文分词器,最后查看 Mapping 配置
- 看到 content 有两个子字段,keyword,以及新增的 english 子字段;
```json
# 修改 Mapping,增加子字段,使用英文分词器
PUT blogs/_mapping
{
"properties" : {
"content" : {
"type" : "text",
"fields" : {
"english" : {
"type" : "text",
"analyzer":"english"
}
}
}
}
}
# 查看 Mapping
GET blogs/_mapping
######### Mapping配置 ############
{
"blogs" : {
"mappings" : {
"properties" : {
"content" : {
"type" : "text",
"fields" : {
"english" : {
"type" : "text",
"analyzer" : "english"
},
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"keyword" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
}
}
}
}
}
- 尝试对子字段进行查询
写入文档
PUT blogs/_doc/2 { “content”:”Elasticsearch rocks”, “keyword”:”elasticsearch” }
查询新写入文档
POST blogs/_search { “query”: { “match”: { “content.english”: “Elasticsearch” } } }
###可以匹配到新写入的文档数据
<a name="MdMCJ"></a>
## 2.1 Update By Query API
:::tips
- 当通过更改 Mapping,索引中某个字段增加了子字段后,那么 Mapping 更改前就已经存在数据是无法针对子字段进行查询的;
- 如果希望对旧有数据针对子字段也可以进行查询,那么可以使用 Update By Query API 对索引下所有文档进行更新;
:::
```json
# Update所有文档
POST blogs/_update_by_query
{
}
3. 案例2:更改已有字段类型的 Mappings
- 查看现有的索引 Mapping 配置
- 如果是对 content 字段下的子字段进行删减或者修改,是可以成功的;
- 如果是对 keyword、content 这样的主字段类型进行修改,text -> keyword,是会报错的;
```json
查看 Mapping
GET blogs/_mapping### Mapping配置
{ “blogs” : { “mappings” : { “properties” : { “content” : {
}, “keyword” : {"type" : "text", "fields" : { "english" : { "type" : "text", "analyzer" : "english" }, "keyword" : { "type" : "keyword", "ignore_above" : 256 } }
} } } } }"type" : "text", "fields" : { "keyword" : { "type" : "keyword", "ignore_above" : 256 } }
修改keyword字段的类型 text->keyword
PUT blogs/_mapping { “properties” : { “content” : { “type” : “text”, “fields” : { “english” : { “type” : “text”, “analyzer” : “english” } } }, “keyword” : { “type” : “keyword” } } }
结果会报错
{ “error”: { “root_cause”: [ { “type”: “illegal_argument_exception”, “reason”: “mapper [keyword] of different type, current_type [text], merged_type [keyword]” } ] } }
<a name="8gslB"></a>
## 3.1 Reindex API
:::tips
- ES 不允许在原有 Mapping 上对字段类型进行修改;
- 只能创建新的索引,并且设定正确的字段类型,再重新导入数据;
- Reindex API 支持把文档从一个索引拷贝到另外一个索引;
- 使用 Reindex API 的一些场景:
- 修改索引的主分片数;
- 改变字段的 Mapping 中的字段类型;
- 集群内数据迁移 / 跨集群的数据迁移;
**注意:**
- Reindex 要求对源索引中的所有文档都启用 _source。
- 在调用 _reindex API 之前,必须设置目标索引。Reindex 不会从源索引复制设置,映射、碎片计数、副本等必须提前配置。
- 一定要尽量使用 Index Alias 读写数据。即便发生 Reindex,也能实现零停机维护。
:::
```json
# 1.创建新的索引 blogs_fix,
并且设定符合新需求的 Mapping,keyword字段类型直接设为 keyword
PUT blogs_fix/
{
"mappings": {
"properties" : {
"content" : {
"type" : "text",
"fields" : {
"english" : {
"type" : "text",
"analyzer" : "english"
}
}
},
"keyword" : {
"type" : "keyword"
}
}
}
}
# 2. Reindx API,将数据从旧索引迁移到新索引
POST _reindex
{
"source": {
"index": "blogs"
},
"dest": {
"index": "blogs_fix"
}
}
# 3.测试,数据已迁移到位
GET blogs_fix/_doc/1
1) op_type:create
- _reindex 只会创建不存在的文档;
文档如果已经存在,会导致版本冲突;
POST _reindex { "source": { "index": "blogs" }, "dest": { "index": "blogs_fix", "op_type": "create" } } #如果存在的文档,会提示迁移失败,失败的原因是文档已存在,导致的版本冲突 { "failures": [ { "index": "blogs_fix", "type": "_doc", "id": "1", "cause": { "type": "version_conflict_engine_exception", "reason": "[1]: version conflict, document already exists (current version [1])", "index_uuid": "Nz6w5rpwTpq3SI7sGiZ8Sw", "shard": "0", "index": "blogs_fix" }, "status": 409 } ] }
2) version_type
缺省 version_type 或设置 version_type: internal,ES 会盲目的将文档迁移到目标索引中,如果目标索引恰好具有相同 ID 的文档,则会被迁移而来的文档覆盖,且 version 增加;
- 设置 version_type: external,ES 会保留源索引中的 version,创建目标索引中不存在的文档,并更新目标索引中 version 比源索引中低的文档(如果目标索引中 _version=2,只有源索引中 _version>2 才能迁移并更新成功,如:源 _version=5,否则报错);
```json
Reindx API
POST _reindex { “source”: { “index”: “blogs” }, “dest”: { “index”: “blogs_fix” } }############## version Type:Internal
Reindx API,version Type Internal,目标索引中已经存在相同id的文档
POST _reindex { “source”: { “index”: “blogs” }, “dest”: { “index”: “blogs_fix”, “version_type”: “internal” } }
不管目标索引中_version是多少,根据源索引中文档版本号增加,文档version: 1->2
GET blogs_fix/_doc/1
############## version Type:External
Reindx API,version Type External,目标索引中已经存在相同id的文档
POST _reindex { “source”: { “index”: “blogs” }, “dest”: { “index”: “blogs_fix”, “version_type”: “external” } }
如果目标索引中 _version=2,只有源索引中 _version>2 才能迁移并更新成功,如:源 _version=5,否则报错
<a name="lytrJ"></a>
### 3) conflicts: proceed
- 默认情况下,版本冲突会终止 Reindex 过程。
- 如果存在冲突时,要继续重建索引,可以设置 "conflicts": "proceed",这种情况下会继续 Reindex 过程,且返回遇到版本冲突的统计数量;
- 注意:其他错误类型的处理不受 "conflicts" 参数的影响;
```json
POST _reindex
{
"source": {
"index": "blogs"
},
"dest": {
"index": "blogs_fix",
"version_type": "external"
},
"conflicts": "proceed"
}
4) 查看 Task API
可以通过查看 Task API,了解 Reindex 的状况
GET _tasks?detailed=true&actions=*reindex
5) Reindex 异步执行
ReIndex API 支持异步操作,执行只返回 Task Id
POST _reindex?wait_for_completion=false
6) 跨集群 Reindex
需要修改 elasticsearch.yaml,并且重启节点
reindex.remote.whitelist: "otherhost:9200, another:9200, 127.0.10.*:9200, localhost:*"
POST _reindex { "source": { "remote": { "host": "http://otherhost:9200", "username": "user", "password": "pass" }, "index": "source", "query": { "match": { "test": "data" } } }, "dest": { "index": "dest" } }