Reindex API
声明:本文根据ES官方文档进行翻译与总结而得。转载请注明作者:https://blog.csdn.net/qingmou_csdn
注意:Reindex不会尝试设置目标索引。它不会复制源索引的设置。您应该在运行
_reindex
操作之前设置目标索引,包括设置映射,分片计数,副本等。
最基本的形式_reindex只是将文档从一个索引复制到另一个索引。如将gaoyh索引中的文档复制到test索引中:
POST _reindex
{
"source": {
"index": "gaoyh"
},
"dest": {
"index": "test"
}
}
响应结果:
{
"took": 161,
"timed_out": false,
"total": 5,
"updated": 0,
"created": 5,
"deleted": 0,
"batches": 1,
"version_conflicts": 0,
"noops": 0,
"retries": {
"bulk": 0,
"search": 0
},
"throttled_millis": 0,
"requests_per_second": -1,
"throttled_until_millis": 0,
"failures": []
}
注意:
就像
_update_by_query
,
_reindex
获取源索引的快照但其目标必须是不同的索引,因此不太可能发生版本冲突。该
dest
元素可以像Index API一样配置,以控制乐观并发控制。只是遗漏
version_type
(如上所述)或将其设置为
internal
将导致Elasticsearch盲目地将文档转储到目标中,覆盖任何碰巧具有相同类型和id的文件:
POST _reindex
{
"source": {
"index": "gaoyh"
},
"dest": {
"index": "test",
"version_type": "internal"
}
}
设置
version_type
为
external
将导致Elasticsearch保留
version
源,创建缺少的任何文档,并更新目标索引中具有旧版本的文档而不是源索引中的任何文档:
POST _reindex
{
"source": {
"index": "gaoyh"
},
"dest": {
"index": "index_test",
"version_type": "external"
}
}
若在索引index_test中,已经存在版本号为1的文档1,而在索引gaoyh中同样存在版本号为1的文档1,则会造成版本冲突,响应结果如下:
{
"took": 33,
"timed_out": false,
"total": 5,
"updated": 0,
"created": 4,
"deleted": 0,
"batches": 1,
"version_conflicts": 1,
"noops": 0,
"retries": {
"bulk": 0,
"search": 0
},
"throttled_millis": 0,
"requests_per_second": -1,
"throttled_until_millis": 0,
"failures": [
{
"index": "index_test",
"type": "test",
"id": "1",
"cause": {
"type": "version_conflict_engine_exception",
"reason": "[test][1]: version conflict, current version [1] is higher or equal to the one provided [1]",
"index_uuid": "Qqk6nvQMQFGE6tw3Xb-PGw",
"shard": "0",
"index": "index_test"
},
"status": 409
}
]
}
即文档1没法从索引gaoyh中复制到索引index_test中;
若索引gaoyh中的文档1的版本号比索引index_test中文档1的版本号高,则会更新索引index_test中的文档1(响应结果如下),此时文档1的版本号等同索引gaoyh中文档1的版本号:
{
"took": 4,
"timed_out": false,
"total": 5,
"updated": 5,
"created": 0,
"deleted": 0,
"batches": 1,
"version_conflicts": 0,
"noops": 0,
"retries": {
"bulk": 0,
"search": 0
},
"throttled_millis": 0,
"requests_per_second": -1,
"throttled_until_millis": 0,
"failures": []
}
设置
op_type为create
会导致
_reindex
在目标指数只会造成文件丢失。所有现有文档都会导致版本冲突,即只能复制目标索引index_test中没有的文档,已有的文档,都不能从gaoyh中复制过来:
POST _reindex
{
"source": {
"index": "gaoyh"
},
"dest": {
"index": "index_test",
"op_type": "create"
}
}
默认情况下,版本冲突会中止该
_reindex
过程,但您可以通过
"conflicts": "proceed"
请求正文中的设置对它们进行计数:
POST _reindex
{
"conflicts": "proceed",
"source": {
"index": "gaoyh"
},
"dest": {
"index": "index_test",
"op_type": "create"
}
}
加上"conflicts": "proceed"后响应结果中不会具体显示failures。
但是,版本冲突时并未造成reindex过程中止。
您可以通过向其添加类型
source
或通过添加查询来限制文档。
如,只复制旧索引twitter中用户kimchy的文档到新索引new_twitter中:
POST _reindex
{
"source": {
"index": "twitter",
"type": "_doc",
"query": {
"term": {
"user": "kimchy"
}
}
},
"dest": {
"index": "new_twitter"
}
}
也可以通过设置来限制处理文档的数量
size
。这只会将单个文档复制
twitter
到
new_twitter
:
POST _reindex
{
"size": 2,
"source": {
"index": "gaoyh"
},
"dest": {
"index": "index_test"
}
}
设置size为2,则会随机从索引gaoyh中选择2个文档复制到新索引index_test中(说是随机,但感觉不是随机的-_-||试了4次,每次都是gaoyh中的文档2和5被复制过来。。)
POST _reindex
{
"source": {
"index": "twitter",
"_source": ["user", "_doc"]
},
"dest": {
"index": "new_twitter"
}
}
像_update_by_query一样,_reindex也支持脚本修改文档。与_update_by_query不一样的是,_reindex允许脚本修改文档的元数据。e.g.
POST _bulk
{"index":{"_index":"gaoyh","_type":"test","_id":"1"}}
{"user":"aaa","content":"test"}
{"index":{"_index":"gaoyh","_type":"test","_id":"2"}}
{"user":"aaa","content":"test"}
{"index":{"_index":"gaoyh","_type":"test","_id":"3"}}
{"user":"ccc","content":"test"}
{"index":{"_index":"gaoyh","_type":"test","_id":"4"}}
{"user":"bbb","content":"test"}
{"index":{"_index":"gaoyh","_type":"test","_id":"5"}}
{"user":"bbb","content":"test"}
PUT index_test
{
"settings":{
"number_of_shards": 1,
"number_of_replicas": 0
},
"mappings": {
"test":{
"properties": {
"user":{
"type": "text"
},
"content":{
"type": "text"
}
}
}
}
}
POST _reindex
{
"source": {
"index": "gaoyh"
},
"dest": {
"index": "index_test",
"version_type": "external"
},
"script": {
"source":"if(ctx._source.user=='aaa'){ctx._version++;ctx._source.remove('user')}",
"lang": "painless"
}
}
GET index_test/test/_mget
{ "ids":["1","2","3","4","5"] }
响应结果如下:
{
"docs": [
{
"_index": "index_test",
"_type": "test",
"_id": "1",
"_version": 2,
"found": true,
"_source": {
"content": "test"
}
},
{
"_index": "index_test",
"_type": "test",
"_id": "2",
"_version": 2,
"found": true,
"_source": {
"content": "test"
}
},
{
"_index": "index_test",
"_type": "test",
"_id": "3",
"_version": 1,
"found": true,
"_source": {
"user": "ccc",
"content": "test"
}
},
{
"_index": "index_test",
"_type": "test",
"_id": "4",
"_version": 1,
"found": true,
"_source": {
"user": "bbb",
"content": "test"
}
},
{
"_index": "index_test",
"_type": "test",
"_id": "5",
"_version": 1,
"found": true,
"_source": {
"user": "bbb",
"content": "test"
}
}
]
}
即:索引gaoyh中user为aaa的文档被脚本删除user字段后并增加版本号后复制到新索引index_test中,索引gaoyh中的文档内容不变。
小结:
与_update_by_query一样,你可以通过设置 ctx.op 更改在目标索引上执行的操作:
- noop
设置 ctx.op = "noop" ,则符合脚本内容的文档将不会被编入目标索引(即不会复制到新索引中);响应结果中会在响应正文(response body)中的noop counter中报告出来;
- delete
设置 ctx.op = "noop" ,则符合脚本内容的文档会在目标索引中删除;响应结果中会在响应正文(response body)中的deleted counter中报告出来;
- 其他
设置 ctx.op为其他任何内容都将返回错误,就像在ctx中设置任何其他字段一样。
你可以改变:_id , _type , _index , _version , _routing ;
设置 _version 为 null 或从 ctx 地图中清除它,相当于发送的索引请求中不包含版本信息,这将导致目标索引中的文档被覆盖重写,不管文档在目标索引上的版本或您在 _reindex 请求中使用的版本类型如何。(虽然设置 ctx._version=null,但是复制到目标索引中的文档的版本号和旧索引中原文档的版本号一样,不会置零)
默认情况下,如果
_reindex
查看带有路由的文档,则除非脚本更改了路由,否则将保留路由。您可以
routing
根据
dest
请求设置更改此设置:
- keep
将针对每个匹配发送的批量请求的路由设置为匹配上的路由。这是默认值;
- discard
设置为每个匹配发送的批量请求的路由为
null
;
- =<some text>
将针对每个匹配发送的批量请求的路由设置为=之后的文本。
例如,您可以使用以下请求将
source
索引中包含公司名称为cat的所有文档复制到路由设置为cat的索引dest中
:
POST _reindex
{
"source": {
"index": "source",
"query": {
"match": {
"company": "cat"
}
}
},
"dest": {
"index": "dest",
"routing": "=cat"
}
}
重新索引以更改字段名称
_reindex
可用于构建具有重命名字段的索引副本。
假设您创建一个包含如下所示文档的索引:
POST test/_doc/1?refresh
{
"text": "words words",
"flag": "foo"
}
但你不喜欢这个名字
flag
,想要用它替换它
tag
。
_reindex
可以为您创建其他索引:
POST _reindex
{
"source": {
"index": "test"
},
"dest": {
"index": "test2"
},
"script": {
"source": "ctx._source.tag = ctx._source.remove(\"flag\")"
}
}
GET test2/_doc/1
return:
{
"found": true,
"_id": "1",
"_index": "test2",
"_type": "_doc",
"_version": 1,
"_source": {
"text": "words words",
"tag": "foo"
}
}
Reindex from Remote
从远程索引
Reindex支持从远程Elasticsearch集群重建索引:
POST _reindex
{
"source": {
"remote": {
"host": "http://otherhost:9200",
"username": "user",
"password": "pass"
},
"index": "source",
"query": {
"match": {
"test": "data"
}
}
},
"dest": {
"index": "dest"
}
}
该
host
参数必须包含方案,主机和端口(例如
https://otherhost:9200
)。的
username
和
password
参数是可选的,并且当它们存在时
_reindex
将连接到使用基本认证远程Elasticsearch节点。
https
使用基本身份验证时一定要使用,否则密码将以纯文本形式发送。
URL参数
除了标准参数等
pretty
,重新索引API还支持
refresh
,
wait_for_completion
,
wait_for_active_shards
,
timeout
,
scroll
和
requests_per_second
。
发送
refresh
url参数将导致刷新请求所写的所有索引。这与Index API的
refresh
参数不同,后者仅导致接收新数据的分片被刷新。
如果请求包含,
wait_for_completion=false
则Elasticsearch将执行一些预检检查,启动请求,然后返回
task
可与
Tasks API
一起使用的取消或获取任务状态的请求。Elasticsearch还将创建此任务的记录作为文档
.tasks/task/${taskId}
。这是你的保留或删除你认为合适。完成后,删除它,以便Elasticsearch可以回收它使用的空间。
wait_for_active_shards
控制在继续重建索引之前必须激活碎片的副本数量。详情请见
此处
。
timeout
控制每个写入请求等待不可用分片变为可用的时间。两者都完全适用于
Bulk API中的工作方式
。由于
_reindex
采用滚动搜索,你还可以指定
scroll
参数来控制多长时间保持“搜索上下文”活着,(例如
?scroll=10m
)。默认值为5分钟。
Reindex是使用批处理实现的,任何故障都会导致整个进程中止,但当前批处理中的所有故障都会被收集到数组中。您可以使用该
conflicts
选项来防止reindex在版本冲突中中止。
切片
重新索引多个索引
Reindex每日指数
见ES官网 Document Reindex API:
https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-reindex.html#docs-reindex-slice