Reindex API 详解

来源:互联网 发布:中文网络男女说唱 编辑:程序博客网 时间:2024/05/22 00:09

Reindex API 详解

只要有使用到elasticsearch的场景,那么或多或少总是会遇到需要重构索引的情况。如果对reindex API不熟悉,那么在遇到重构的时候,必然事倍功半,效率低下,一整天都不开心。

在开始讲解具体的API的时候,有一点必须知道,Reindex不会尝试设置目标索引。它不会复制源索引的设置。您应该在运行_reindex操作之前设置目标索引,包括设置映射,分片计数,副本等。当然,最常见的做法不会是手动的设置索引。而是使用索引模版。只要索引模版的匹配形式可以匹配上源索引和目标索引,则我们不需要去考虑索引配置的问题,模版会为我们解决对应的问题。

另外,下文只针对5.x及以后版本。

基本操作

对于reindex API来说,最常见的,就是简单的把documents从一个index复制到另一个。下面的例子中,我们把twitter index的内容复制到new_twitter index中:

POST _reindex{  "source": {    "index": "twitter"  },  "dest": {    "index": "new_twitter"  }}

返回到结果如下:

{  "took" : 147,  "timed_out": false,  "created": 120,  "updated": 0,  "deleted": 0,  "batches": 1,  "version_conflicts": 0,  "noops": 0,  "retries": {    "bulk": 0,    "search": 0  },  "throttled_millis": 0,  "requests_per_second": -1.0,  "throttled_until_millis": 0,  "total": 120,  "failures" : [ ]}

version_type

就像_update_by_query,_reindex会生成源索引的快照(snapshot),但它的目标必须是一个不同的索引,以便避免版本冲突。dest对象可以像index API一样进行配置,以乐观锁控制并发。像上面那样,不设置version_type或设置它将设置为internal。Elasticsearch将会直接将文档转储到dest中,覆盖任何发生的具有相同类型和id的document:

POST _reindex{  "source": {    "index": "twitter"  },  "dest": {    "index": "new_twitter",    "version_type": "internal"  }}

如果把version_type设置为external.则elasticsearch会从source读取version字段,当遇到具有相同类型和id的documents,只更新newer verion。

POST _reindex{  "source": {    "index": "twitter"  },  "dest": {    "index": "new_twitter",    "version_type": "external"  }}

上面说起来似乎有点不好理解。简单说来,就是在redinex的时候,你的dest index可以不是一个新的index,而是包含有数据的。如果你的source indexh和dest index里面有相同类型和id的document.对于使用internal,是直接覆盖。使用external的话,只有当source的version更加新的时候,才更新。

op_type

op_type设置为create,_reindex API,只在dest index中添加不不存在的doucments。如果相同的documents已经存在,则会报version confilct的错误。

POST _reindex{  "source": {    "index": "twitter"  },  "dest": {    "index": "new_twitter",    "op_type": "create"  }}

conflicts配置

默认情况下,当发生version conflict的时候,_reindex会被abort。除非把conflicts设置为“proceed”:

POST _reindex{  "conflicts": "proceed",  "source": {    "index": "twitter"  },  "dest": {    "index": "new_twitter",    "op_type": "create"  }}

query配置

我们还可以通过query,把需要_reindex的document限定在一定的范围。下面的例子,就只copy了作者是’kimchy’的twitter到new_twitter:

POST _reindex{  "source": {    "index": "twitter",    "type": "tweet",    "query": {      "term": {        "user": "kimchy"      }    }  },  "dest": {    "index": "new_twitter"  }}

将多个索引reindex到一个目标

POST _reindex{  "source": {    "index": ["twitter", "blog"],    "type": ["tweet", "post"]  },  "dest": {    "index": "all_together"  }}

这里要注意的是,如果twitter和blog中有document的id是一样的,则无法保证最终出现在all_together里面的document是哪个,因为迭代是随机的。(最后一个会覆盖前一个)

size设置

通过size可以控制复制多少内容,下例只复制了一个document:

POST _reindex{  "size": 1,  "source": {    "index": "twitter"  },  "dest": {    "index": "new_twitter"  }}

sort配置

下例,把时间排序前10000个document,复制到目标:

POST _reindex{  "size": 10000,  "source": {    "index": "twitter",    "sort": { "date": "desc" }  },  "dest": {    "index": "new_twitter"  }}

只复制特定的field

POST _reindex{  "source": {    "index": "twitter",    "_source": ["user", "tweet"]  },  "dest": {    "index": "new_twitter"  }}

使用script

POST _reindex{  "source": {    "index": "twitter"  },  "dest": {    "index": "new_twitter",    "version_type": "external"  },  "script": {    "source": "if (ctx._source.foo == 'bar') {ctx._version++; ctx._source.remove('foo')}",    "lang": "painless"  }}

使用Ingest Node

这个功能应该说是最好用的了。当你的source是因为不合理的结构,需要重新结构化所有的数据时,通过ingest node, 可以很方便的在新的index中获得不一眼的mapping和value:

POST _reindex{  "source": {    "index": "source"  },  "dest": {    "index": "dest",    "pipeline": "some_ingest_pipeline"  }}

reindex远程服务器的索引到本地

使用remote属性:

POST _reindex{  "source": {    "remote": {      "host": "http://otherhost:9200",      "username": "user",      "password": "pass"    },    "index": "source",    "query": {      "match": {        "test": "data"      }    }  },  "dest": {    "index": "dest"  }}

对于在其他集群上的index,就不存在本地镜像复制的便利。需要从网络上下载数据再写到本地,默认的,buffer的size是100M。在scroll size是1000的情况下,如果单个document的平均大小超过100Kb,则有可能会报错。因此在在遇到非常大的documents,需要减小batch的size:

POST _reindex{  "source": {    "remote": {      "host": "http://otherhost:9200"    },    "index": "source",    "size": 100,    "query": {      "match": {        "test": "data"      }    }  },  "dest": {    "index": "dest"  }}

Response body

一般来说,是这样的:

{  "took" : 639,  "updated": 0,  "created": 123,  "batches": 1,  "version_conflicts": 2,  "retries": {    "bulk": 0,    "search": 0  }  "throttled_millis": 0,  "failures" : [ ]}

这里要注意的是failures,如果里面的值不为空,则代表本次_reindex是失败的,是被中途abort,一般都是因为发生了conflicts。前面已经说过,如何设置,在发生conflict的时候继续运行。

使用Task API查询进度

一般来说,如果你的source index很大,则可能需要比较长的时间来完成_reindex的工作。如果需要查看进度,可以通过_tasks API:

GET _tasks?detailed=true&actions=*reindex

返回结果如下:

{  "nodes" : {    "r1A2WoRbTwKZ516z6NEs5A" : {      "name" : "r1A2WoR",      "transport_address" : "127.0.0.1:9300",      "host" : "127.0.0.1",      "ip" : "127.0.0.1:9300",      "attributes" : {        "testattr" : "test",        "portsfile" : "true"      },      "tasks" : {        "r1A2WoRbTwKZ516z6NEs5A:36619" : {          "node" : "r1A2WoRbTwKZ516z6NEs5A",          "id" : 36619,          "type" : "transport",          "action" : "indices:data/write/reindex",          "status" : {                "total" : 6154,            "updated" : 3500,            "created" : 0,            "deleted" : 0,            "batches" : 4,            "version_conflicts" : 0,            "noops" : 0,            "retries": {              "bulk": 0,              "search": 0            },            "throttled_millis": 0          },          "description" : ""        }      }    }  }}

上面表示,一共需要处理6154个document,现在已经update了3500个。

取消reindex

射出去的箭还是可以收回的,通过_tasks API:

POST _tasks/task_id:1/_cancel

这里的task_id,可以通过上面的å_tasks API获得。

原创粉丝点击