重新 索引API - shuiyuebingdian/ElasticSearch GitHub Wiki

Reindex API

Reindex不会尝试设置目标索引。它不会复制源索引的设置。您应该在执行_reindex操作之前设置目标索引,包括设置映射,分片计数,副本等。
最基本的形式_reindex只是将文档从一个索引复制到另一个索引。这会将文档从twitter索引复制到new_twitter索引中:

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" : [ ]
}

就像_update_by_query一样,_reindex获取源索引的快照,但是其目标必须是其他索引,因此不会发生版本冲突。dest元素设置可以和索引API控制乐观并发控制一样,要么只是忽略 version_type(如上)或将其设置为internal将导致Elasticsearch盲目地将文档转储到目标中,覆盖碰巧具有相同类型和id的所有文档:

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

设置version_type为external将会导致Elasticsearch保留source的版本,创建任何丢失的文档,并更新目标索引中比源索引中具有旧版本的文档:

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

设置op_type为create将导致_reindex仅在目标索引中创建丢失的文档。所有现有文档将导致版本冲突:

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

默认情况下,版本冲突会中止该_reindex过程,但是您可以通过"conflicts": "proceed"请求正文中的设置来计算它们:

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

您可以通过在中添加类型source或通过添加查询来限制文档。这只会复制tweet的由制造kimchy到new_twitter:

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

index和type在source里既可以是列表,让您可以从一个请求中复制大量的资源。下面一个例子将从tweeter和blog索引中的tweet和 post中的类型复制文档。它会包含twitter索引中的post类型和blog索引中的tweet类型。如果您想更具体一些,则需要使用query。它还不费力地处理ID冲突。目标索引将保持有效,但由于迭代顺序定义不明确,因此很难预测哪个文档将继续存在。

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

通过设置也可以限制已处理文档的数量 size。这只会将一个文档从复制twitter到 new_twitter:

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

如果要从twitter索引中获取一组特定的文档,则需要进行排序。排序会使滚动效率降低,但在某些情况下值得这样做。如果可能的话,请优先选择sizeand和sort。这会将10000个文档从复制twitter到new_twitter:

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

本source部分支持搜索请求中支持的所有元素 。例如,可以使用源过滤如下重新索引原始文档中的一部分字段:

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

像一样_update_by_query,_reindex支持修改文档的脚本。不同于_update_by_query,该脚本允许修改文档的元数据。此示例增加了源文档的版本:

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

就像在_update_by_query中一样,您可以设置ctx.op更改在目标索引上执行的操作:

noop
设置ctx.op = "noop"是否由脚本确定不必在目标索引中为文档建立索引。不会noop在响应正文的计数器中报告此操作。 delete
设置ctx.op = "delete"脚本是否决定必须从目标索引中删除该文档。删除将deleted在响应正文中的计数器中报告 。 设置ctx.op为其他任何东西都是错误的。在其中设置任何其他字段ctx是错误的。

想想可能性!请注意!具有强大的力量... 你可以改变:

  • _id
  • _type
  • _index
  • _version
  • _routing
  • _parent
    设置_version到null或从清除它ctx的地图就像是在一个索引请求不发送版本。无论目标上的版本或_reindex请求中使用的版本类型如何,都会导致该文档在目标索引中被覆盖。

默认情况下,如果_reindex看到带有路由的文档,则路由将保留,除非脚本更改了路由。您可以routing根据 dest请求进行更改:

keep
将为每个匹配发送的批量请求上的路由设置为匹配上的路由。默认值。
discard
将针对每个匹配发送的批量请求的路由设置为null。
=<some text>
将针对每次匹配发送的批量请求的路由设置为之后的所有文本=。
例如,您可以使用以下请求source将公司名称从索引中的所有文档复制cat到dest路由设置为的索引中cat。

POST _reindex
{
  "source": {
	"index": "source",
	"query": {
	  "match": {
		"company": "cat"
	  }
	}
  },
  "dest": {
	"index": "dest",
	"routing": "=cat"
  }
}

默认情况下,_reindex使用滚动批处理1000。您可以使用元素中的size字段更改批处理大小source:

POST _reindex
{
  "source": {
	"index": "source",
	"size": 100
  },
  "dest": {
	"index": "dest",
	"routing": "=cat"
  }
}

Reindex也可以通过指定如下所示来使用Ingest Node功能 pipeline:

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

从远程重新索引

重新索引支持从远程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参数是可选的,当它们存在时重新索引将连接到使用基本认证远程Elasticsearch节点。https使用基本身份验证时请务必使用,否则密码将以纯文本形式发送。

必须使用reindex.remote.whitelist属性在elasticsearch.yaml中将远程主机明确列入白名单 。可以将其设置为以逗号分隔的允许的遥控器host和port组合列表(例如 otherhost:9200, another:9200, 127.0.10.:9200, localhost:)。白名单将忽略方案-仅使用主机和端口。

此功能应可用于您可能会发现的任何版本的Elasticsearch的远程集群。这应该允许您通过从旧版本的集群重新索引来从Elasticsearch的任何版本升级到当前版本。

要启用发送到旧版本Elasticsearch的查询,该query参数无需验证或修改即可直接发送到远程主机。

从远程群集重新索引不支持 手动或 自动切片。

从远程服务器重新索引使用堆上缓冲区,该缓冲区默认最大大小为100mb。如果远程索引包含非常大的文档,则需要使用较小的批处理大小。下面的示例将批次大小设置为10 非常小。

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

也可以通过该socket_timeout字段在远程连接上设置套接字读取超时,并通过该字段 设置套接字超时connect_timeout。两者默认为三十秒。本示例将套接字读取超时设置为一分钟,将连接超时设置为十秒:

POST _reindex
{
  "source": {
	"remote": {
	  "host": "http://otherhost:9200",
	  "socket_timeout": "1m",
	  "connect_timeout": "10s"
	},
	"index": "source",
	"query": {
	  "match": {
		"test": "data"
	  }
	}
  },
  "dest": {
	"index": "dest"
  }
}

URL参数

除了标准参数等pretty,重新索引API还支持refresh,wait_for_completion,wait_for_active_shards,timeout,和 requests_per_second。

发送refreshurl参数将刷新请求写入的所有索引。这与Index API的refresh 参数不同,后者仅导致接收新数据的分片被刷新。

如果请求包含,wait_for_completion=false则Elasticsearch将执行一些预检检查,启动请求,然后返回task ,可与Tasks API 一起使用来取消或获取任务的状态。Elasticsearch还将在上创建此任务的记录作为文档.tasks/task/${taskId}。您可以根据自己的喜好保留或删除此文件。完成后,将其删除,以便Elasticsearch可以回收其使用的空间。

wait_for_active_shards控制在进行重新索引编制之前必须处于活动状态的分片副本数。有关 详细信息,请参见此处。timeout控制每个写入请求等待不可用的碎片变为可用的时间。两者都可以在Bulk API中正常工作 。

requests_per_second可以被设置为任何正十进制数(1.4,6, 1000等),并在其通过填充每个批次由一等待时间重新索引索引操作的问题批次节流率。将设置requests_per_second为可以禁用节流-1。

节流是通过在批处理之间等待来完成的,以便可以给内部索引使用的滚动指定一个超时,该超时将填充考虑在内。填充时间是批大小除以requests_per_second和所花费的时间之间的差 。默认情况下,批处理大小为 1000,因此如果将requests_per_second设置为500:

target_time = 1000 / 500 per second = 2 seconds
wait_time = target_time - write_time = 2 seconds - .5 seconds = 1.5 seconds

由于批次是作为单个_bulk请求发出的,因此较大的批次大小将导致Elasticsearch创建许多请求,然后等待一段时间,然后再开始下一组请求。这是“突发的”而不是“平滑的”。默认值为-1。

响应体

JSON响应如下所示:

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

took
从整个操作开始到结束的毫秒数。
updated
成功更新的文档数。
created
成功创建的文档数。
batches
重新索引拉回的滚动响应数。
version_conflicts
重新索引命中的版本冲突数。
retries
重新索引尝试的重试次数。bulk是重试的批量操作search数,也是重试的搜索操作数。
throttled_millis
要求遵守的毫秒数requests_per_second。
failures
所有索引失败的数组。如果这是非空的,则请求由于这些失败而中止。有关conflicts如何防止版本冲突中止操作的信息,请参阅。

与Task API配合使用

您可以使用Task 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" : ""
		}
	  }
	}
  }
}

该对象包含实际状态。就像响应json加上重要的total字段一样。total是重新索引期望执行的操作总数。您可以通过添加估计的进展updated,created以及deleted多个领域。当它们的总和等于total字段时,请求将结束。

使用任务ID,您可以直接查找任务:

GET /_tasks/taskId:1

该API的优势在于它与之集成wait_for_completion=false 以透明地返回已完成任务的状态。如果任务已完成并wait_for_completion=false设置在任务上,它将返回一个 results或error字段。此功能的成本是在wait_for_completion=false创建的文档 .tasks/task/${taskId}。由您决定删除该文档。

与Cancel Task API一起使用

可以使用Task Cancel API取消任何重新索引:

POST _tasks/task_id:1/_cancel

在task_id可以使用上述任务的API被发现。

取消应该很快发生,但可能需要几秒钟。上面的任务状态API将继续列出任务,直到唤醒它以取消自身为止。

重新调节

requests_per_second可以使用_rethrottleAPI 在正在运行的重新索引上更改的值:

POST _reindex/task_id:1/_rethrottle?requests_per_second=-1

在task_id可以使用上述任务的API被发现。

就像在_reindexAPI requests_per_second 上进行设置一样,可以-1禁用限制或任何十进制数字,1.7或12将其限制为该级别。重新调速(加快查询速度)立即生效,但重新调速(降低查询速度)将在完​​成当前批次后生效。这样可以防止滚动超时。

重新索引以更改字段名称

_reindex可用于构建具有重命名字段的索引副本。假设您创建一个包含如下文档的索引:

POST test/test/1?refresh
{
  "text": "words words",
  "flag": "foo"
}

但是您不喜欢该名称flag,而是希望将其替换为tag。 _reindex可以为您创建另一个索引:

POST _reindex
{
  "source": {
	"index": "test"
  },
  "dest": {
	"index": "test2"
  },
  "script": {
	"inline": "ctx._source.tag = ctx._source.remove(\"flag\")"
  }
}

现在您可以获取新文档:

GET test2/test/1

它看起来像:

{
  "found": true,
  "_id": "1",
  "_index": "test2",
  "_type": "test",
  "_version": 1,
  "_source": {
	"text": "words words",
	"tag": "foo"
  }
}

或者,您可以根据tag自己的意愿进行搜索。

手动切片

Reindex支持Sliced Scroll,使您可以相对轻松地手动并行化流程:

POST _reindex
{
  "source": {
	"index": "twitter",
	"slice": {
	  "id": 0,
	  "max": 2
	}
  },
  "dest": {
	"index": "new_twitter"
  }
}
POST _reindex
{
  "source": {
	"index": "twitter",
	"slice": {
	  "id": 1,
	  "max": 2
	}
  },
  "dest": {
	"index": "new_twitter"
  }
}

验证:

GET _refresh
POST new_twitter/_search?size=0&filter_path=hits.total

结果total是这样的:

{
  "hits": {
	"total": 120
  }
}

自动切片

您还可以使用切片滚动让reindex自动并行化以切片_uid:

POST _reindex?slices=5&refresh
{
  "source": {
	"index": "twitter"
  },
  "dest": {
	"index": "new_twitter"
  }
}

验证:

POST new_twitter/_search?size=0&filter_path=hits.total

结果total是这样的:

{
  "hits": {
	"total": 120
  }
}

添加slices到_reindex可以自动完成上一节中使用的手动过程,创建子请求,这意味着它有一些怪癖:

  • 您可以在Tasks API中看到这些请求。这些子请求是带有的请求任务的“子”任务slices。
  • 获取请求的任务状态slices仅包含已完成切片的状态。
  • 这些子请求可分别用于取消和限制操作。
  • 重新限制请求slices将按比例重新限制未完成的子请求。
  • 使用取消请求slices将取消每个子请求。
  • 由于slices每个子请求的性质,将无法获得完全均匀的文档部分。将处理所有文档,但是某些切片可能比其他切片大。期望更大的切片具有更均匀的分布。
  • 带有requests_per_second和size带有请求的 参数与slices 每个子请求成比例地分布。结合上面关于分配不均的观点,您应该得出结论,使用 sizewith slices可能不会完全对size文档进行“ _reindex”编辑。
  • 每个子请求都将获得源索引的快照略有不同的快照,尽管它们都是在大约同一时间拍摄的。

挑选切片数

此时,我们slices对使用的数量提出了一些建议(max如果手动并行化,则使用slice API中的参数):

  • 不要使用大量数字。500会造成相当大的CPU抖动。
  • 从查询性能的角度来看,在源索引中使用分片数量的一些倍数会更有效。
  • 从查询性能的角度来看,使用与源索引中的数量一样多的分片是最有效的。
  • 索引性能应在可用资源范围内线性扩展,数量为slices。
  • 索引还是查询性能在该过程中占主导地位,取决于许多因素,例如正在重新建立索引的文档以及正在执行重新建立索引的集群。

重新索引每日索引

您可以_reindex结合使用Painless 来重新索引每日索引,以将新模板应用于现有文档。

假设您具有由以下文件组成的索引:

PUT metricbeat-2016.05.30/beat/1?refresh
{"system.cpu.idle.pct": 0.908}
PUT metricbeat-2016.05.31/beat/1?refresh
{"system.cpu.idle.pct": 0.105}

metricbeat-*索引的新模板已经加载到elasticsearch中,但仅适用于新创建的索引。无痛可用于重新索引现有文档并应用新模板。

下面的脚本从索引名称中提取日期,并创建一个-1附加了新索引的索引。来自的所有数据metricbeat-2016.05.31都将重新索引到中metricbeat-2016.05.31-1。

POST _reindex
{
  "source": {
	"index": "metricbeat-*"
  },
  "dest": {
	"index": "metricbeat"
  },
  "script": {
	"lang": "painless",
	"inline": "ctx._index = 'metricbeat-' + (ctx._index.substring('metricbeat-'.length(), ctx._index.length())) + '-1'"
  }
}

现在,可以在*-1索引中找到以前的metricbeat索引中的所有文档。

GET metricbeat-2016.05.30-1/beat/1
GET metricbeat-2016.05.31-1/beat/1

先前的方法也可以与更改字段名称结合使用, 以仅将现有数据加载到新索引中,还可以根据需要重命名字段。

提取索引的随机子集

Reindex可用于提取索引的随机子集以进行测试:

POST _reindex
{
  "size": 10,
  "source": {
	"index": "twitter",
	"query": {
	  "function_score" : {
		"query" : { "match_all": {} },
		"random_score" : {}
	  }
	},
	"sort": "_score"    
  },
  "dest": {
	"index": "random_twitter"
  }
}

Reindex默认为排序依据,_doc因此random_score除非您将排序覆盖为,否则不会有任何效果_score。

⚠️ **GitHub.com Fallback** ⚠️