在我们开发的过程中,我们有很多时候需要用到 Reindex 接口。它可以帮我们把数据从一个 index 到另外一个 index 进行重新 reindex。这个对于特别适用于我们在修改我们数据的 mapping 后,需要重新把数据从现有的 index 转到新的 index 建立新的索引,这是因为我们不能修改现有的 index 的 mapping 一旦已经定下来了。在接下来的介绍中,我们将学习如何使用 reindex 接口。

为了能够使用 reindex 接口,我们必须满足一下的条件:

  • _source 选项对所有的源 index 文档是启动的,也即源 index 的 source 是已经被存储的
  • reindex 不是帮我们尝试设置好目的地 index。它不拷贝源 index 的设置到目的地的 index 里去。你应该在做 reindex 之前把目的地的源的 index 设置好,这其中包括 mapping, shard 数目,replica 等

下面,我们来一个具体的例子,比如建立一个 blogs 的 index。

PUT twitter2/_doc/1
{"user" : "双榆树-张三","message" : "今儿天气不错啊,出去转转去","uid" : 2,"age" : 20,"city" : "北京","province" : "北京","country" : "中国","address" : "中国北京市海淀区","location" : {"lat" : "39.970718","lon" : "116.325747"}
}

上面的命令让我们建立了一个叫做 twitter2 的 index,并同时帮我们生产了一个如下的 mapping:

GET /twitter2/_mapping

显示的结果是:

{"twitter2" : {"mappings" : {"properties" : {"address" : {"type" : "text","fields" : {"keyword" : {"type" : "keyword","ignore_above" : 256}}},"age" : {"type" : "long"},"city" : {"type" : "text","fields" : {"keyword" : {"type" : "keyword","ignore_above" : 256}}},"country" : {"type" : "text","fields" : {"keyword" : {"type" : "keyword","ignore_above" : 256}}},"location" : {"properties" : {"lat" : {"type" : "text","fields" : {"keyword" : {"type" : "keyword","ignore_above" : 256}}},"lon" : {"type" : "text","fields" : {"keyword" : {"type" : "keyword","ignore_above" : 256}}}}},"message" : {"type" : "text","fields" : {"keyword" : {"type" : "keyword","ignore_above" : 256}}},"province" : {"type" : "text","fields" : {"keyword" : {"type" : "keyword","ignore_above" : 256}}},"uid" : {"type" : "long"},"user" : {"type" : "text","fields" : {"keyword" : {"type" : "keyword","ignore_above" : 256}}}}}}
}

显然根据我们之前的练习 “开始使用Elasticsearch (2)”,系统帮我们生产的 location 数据类型是不对的,我们必须进行修改。一种办法是删除现有的 twitter2 索引,让后修改它的 mapping,再重新索引所有的数据。这对于一个两个文档还是可以的,但是如果已经有很多的数据了,这个方法并不可取。另外一种方式,是建立一个完全新的 index,使用新的 mapping 进行 reindex。下面我们展示如何使用这种方法。

创建一个新的 twitter3 的 index,使用如下的 mapping:

PUT twitter3
{"settings": {"number_of_shards": 1,"number_of_replicas": 1},"mappings": {"properties": {"address": {"type": "text","fields": {"keyword": {"type": "keyword","ignore_above": 256}}},"age": {"type": "long"},"city": {"type": "text"},"country": {"type": "text"},"location": {"type": "geo_point"},"message": {"type": "text","fields": {"keyword": {"type": "keyword","ignore_above": 256}}},"province": {"type": "text"},"uid": {"type": "long"},"user": {"type": "text"}}}
}

这里我们我们修改了 location 及其它的一些数据项的数据类型。运行上面的指令,我们就可以创建一个完全新的 twitter3 的 index。我们可以通过如下的命令来进行 reindex:

POST _reindex
{"source": {"index": "twitter2"},"dest": {"index": "twitter3"}
}

显示的结果是:

{"took" : 52,"timed_out" : false,"total" : 1,"updated" : 0,"created" : 1,"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,"failures" : [ ]
}

我们可以通过如下的命令来检查我们的 twitter3 是否已经有新的数据:

GET /twitter3/_search

显示的结果是:

{"took" : 100,"timed_out" : false,"_shards" : {"total" : 1,"successful" : 1,"skipped" : 0,"failed" : 0},"hits" : {"total" : {"value" : 1,"relation" : "eq"},"max_score" : 1.0,"hits" : [{"_index" : "twitter3","_type" : "_doc","_id" : "1","_score" : 1.0,"_source" : {"user" : "双榆树-张三","message" : "今儿天气不错啊,出去转转去","uid" : 2,"age" : 20,"city" : "北京","province" : "北京","country" : "中国","address" : "中国北京市海淀区","location" : {"lat" : "39.970718","lon" : "116.325747"}}}]}
}

显然我们的数据已经从 twitter2 到 twitter3,并且它的数据类型已经是完全符合我们要求的数据类型。

在执行 reindex 的时候,为了提高效率,我们可以通过设置 slices 参数来并行处理。在通常的情况下,我们可以设置 slices为 auto 让 Elasticsearch 自动选择 slices 的数目来进行加速。Elasticsearch 会依据你电脑中的 core 的数量来进行决定。我们可以使用如下的格式:

POST _reindex?slices=auto
{"source": {"index": "twitter2"},"dest": {"index": "twitter3"}
}

Reindex 执行

  • Reindex 是一个时间点的副本
  • 就像上面返回的结果显示的那样,它是以 batch(批量)的方式来执行的。默认的批量大小为 1000
  • 你也可以只拷贝源 index 其中的一部分数据

-  通过加入 query 到 source 中

-  通过定义 max_docs 参数

比如:

POST _reindex
{"max_docs": 100,"source": {"index": "twitter2","query": {"match": {"city": "北京"}}},"dest": {"index": "twitter3"}
}

这里,我们定义最多不超过 100 个文档,同时,我们只拷贝来自“北京”的 twitter 记录。

设置 op_type to create 将导致 _reindex 仅在目标索引中创建缺少的文档。 所有现有文档都会导致版本冲突,比如:

POST _reindex
{"source": {"index": "twitter2"},"dest": {"index": "twitter3","op_type": "create"}
}

如果我们之前已经做过 reindex,那么我们可以看到如下的结果:

{"took": 2,"timed_out": false,"total": 1,"updated": 0,"created": 0,"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": "twitter3","type": "_doc","id": "1","cause": {"type": "version_conflict_engine_exception","reason": "[1]: version conflict, document already exists (current version [5])","index_uuid": "ffz2LNIIQqqDx211R5f4fQ","shard": "0","index": "twitter3"},"status": 409}]
}

它表明我们之前的文档 id 为1的有版本上的冲突。

默认情况下,版本冲突会中止 _reindex 进程。 “conflict” 请求 body 参数可用于指示 _reindex 继续处理版本冲突的下一个文档。 请务必注意,其他错误类型的处理不受 “conflict” 参数的影响。 当 “conflict”:在请求正文中设置 “proceed” 时, _reindex 进程将继续发生版本冲突并返回遇到的版本冲突计数:

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

Throttling

重新索引大量文档可能会使你的群集泛滥甚至崩溃。requests_per_second 限制索引操作速率。

POST _reindex?requests_per_second=500
{"source": {"index": "blogs","size": 500},"dest": {"index": "blogs_fixed"}
}

运用 index 别名来进行 reindex

我们可以通过如下的方法来实现从一个 index 到另外一个 index 的数据转移:

PUT test
PUT test_2
POST /_aliases
{"actions" : [{ "add":  { "index": "test_2", "alias": "test" } },{ "remove_index": { "index": "test" } }  ]
}

在上面的例子中,假如我们地添加了一个叫做 test 的 index,而 test_2 是我们想要的。我们直接可以通过上面的方法吧 test 中的数据交换到 test_2 中,并同时把 test 索引删除。

从远处进行 reindex

_reindex 也支持从一个远处的 Elasticsearch 的服务器进行 reindex,它的语法为:

POST _reindex
{"source": {"index": "blogs","remote": {"host": "http://remote_cluster_node1:9200","username": "USERNAME","password": "PASSWORD"}},"dest": {"index": "blogs"}
}

这里显示它从一个在 http://remote_cluster_node1:9200 的服务器来拷贝文件从一个 index 到另外一个 index。我们必须注意的是:remote hosts 必须很清楚地在 elasticsearch.yml 这个配置文件中的 reindex.remote.whitelist 中进行定义。比如你可以在 config/elasticsearch.yml 中进行如下的定义:

config/elasticsearch.yml

reindex.remote.whitelist: ["remote_cluster_node1:9200"]

Reindex API 允许你调用远程集群。 请注意,每个版本的 Elasticsearch 服务器都受支持。 reindex API 对远程索引集群执行扫描查询,并将数据放入当前集群。 此过程可能需要很长时间,具体取决于需要复制的数据量以及索引数据所需的时间。

source 分包含控制获取数据的重要参数,例如:

  • remote:这是包含有关远程集群连接信息的部分。
  • index:这是必须用于获取数据的远程索引; 它也可以是别名或通过 glob 模式(比如 twitter*)的多个索引。
  • query:该参数是可选的; 这是一个标准查询,可用于选择必须复制的文档。
  • size:此参数是可选的,缓冲区最大为 200 MB——即用于批量读写操作的文档数。

配置的 remote 部分由以下参数组成:

  • host:集群的远程 REST 端点
  • username:用于复制数据的用户名(这是一个可选参数)
  • password:用户访问远程集群的密码(可选参数)

和标准的 snapshot 和 restore 相比较,上使用这种方法有很多优点,包括:

  • 从旧集群(即版本 1.x 或更高版本)复制数据的能力。
  • 使用查询从选定的文档中复制的能力。 这对于将数据从生产集群复制到开发或测试集群非常方便。

Update by Query

虽然这个不在我们的 reindex 介绍范围,但是在有些情况下,我们可以可以通过 _update_by_query API 来让我们轻松地更新一个字段的值:

POST blogs_fixed/_update_by_query
{"query": {"match": {"category.keyword": ""}},"script": {"source": """ctx._source['category'] = "None""""}
}

在上面,把 category.keyword 项为空的所有文档的 category 通过脚本设置为默认的 "None" 字符串。它和 reindex 的作用相似。

为 mapping 添加新的 mulit-field

假设我们要向 twitter_new 索引的 mapping 添加一个多字段(multi-field)

  • 具体来说,假设我们要用新的方法分析 “content” 字段
PUT new_new/_mapping
{"properties": {"content": {"type": "text","fields": {"english": {"type": "text","analyzer": "english"}}}}
}

在上面我们为 content 字段添加了一个新的 english 字段,并且它的 analyzer 为 english。

由于 mapping 已经发生改变,但是索引中已经有的文档没有这个新的字段 english,如果这个时候我们进行如下的搜索,将不会找到任何的结果:

GET twitter_new/_search
{"query": {"match": {"content.english": "performance tips"}}
}

那么我们该如何使得索引中现有的文档都有 content.english 这个字段呢?运行 _update_by_query 以拥有现有文档选择新的 “content.english” 字段:

POST twitter_new/_update_by_query

当我们完成上面的请求后,然后再执行如下的操作,将会在 twitter_new 索引中搜索到想要的文档:

GET twitter_new/_search
{"query": {"match": {"content.english": "performance tips"}}
}

更多阅读:Elasticsearch:如何轻松安全地对实时 Elasticsearch 索引重新索引你的数据

参考:

【1】Reindex API | Elasticsearch Guide [7.3] | Elastic

Elasticsearch: Reindex 接口相关推荐

  1. 干货 | Elasticsearch Reindex性能提升10倍+实战

    Elasticsearch 最少必要知识实战教程直播回放 #1.reindex的速率极慢,是否有办法改善? 以下问题来自社区:https://elasticsearch.cn/question/378 ...

  2. ElasticSearch reindex 使用

    ElasticSearch reindex 使用 处理:ElasticSearch reindex 超时 "error": "Gateway Time-out" ...

  3. ElasticSearch:Reindex数据迁移使用

    一.前言 ES在创建好索引后,mapping的properties属性类型是不能更改的,只能添加.如果说需要修改字段就需要重新建立索引然后把旧数据导到新索引. 二.Reindex 5.X版本后新增_r ...

  4. Elasticsearch reindex 和批量写入调优

    假设有这样一个index. 我们发现 latency的类型声明错了,但是在es中,类型是不允许修改的. 这时候可以使用 reindex 进行操作.reindex可以理解为,把数据从一个索引中批量导入到 ...

  5. Elasticsearch API接口介绍

    容量控制 _split接口 _split接口可以在新索引中将每个主分片分裂为两个或更多分片,所以使用split扩容时分片总量都是成倍增加而不能逐个增加.使用split接口分裂分片虽然会创建新的索引,但 ...

  6. Elasticsearch:运用 distance feature 查询来增强相关性

    提高文档的相关性得分,使其更接近提供的原始日期或地点. 例如,你可以使用此查询为更接近某个日期或位置的文档赋予更大的权重. 你可以使用 distance_feature 查询查找与某个位置最近的邻居. ...

  7. Elasticsearch:路由 - routing

    你是否考虑过 Elasticsearch 如何知道将文档存储在何处? 它如何知道在哪里寻找它们,以及是否检索.更新或删除它们? 这是一个令人兴奋的过程,一切都归结为路由的概念. 路由介绍 路由是确定文 ...

  8. 【elasticsearch】ES数据库重建索引 -- Reindex(数据迁移)

    1.应用背景: 1.当你的数据量过大,而你的索引最初创建的分片数量不足,导致数据入库较慢的情况,此时需要扩大分片的数量,此时可以尝试使用Reindex. 2.当数据的mapping需要修改,但是大量的 ...

  9. 教你如何在 elasticsearch 中重建索引

    序言 Elasticsearch 是一个实时的分布式搜索分析引擎.Teambition 使用 Elastisearch 作为搜索引擎,为用户提供搜索服务,当我们决定存储某种数据时,我们需要使用PUT ...

最新文章

  1. UIUC教授季姮:叫我带头人,而不是女性带头人(附视频)
  2. ISE下载到FPGA内的文件格式
  3. seata 集群_【视频】 聊聊分布式事务解决方案seata
  4. why I cannot set SAP UI5 dropdown list as not selected
  5. 使用NPOI库导入导出EXCEL
  6. mysql 自身参照自身_MySQL入门
  7. android图片传输三方框架,Android开发三种第三方图片加载的框架
  8. 深度学习中的“卷积”与数学中的“卷积”有何不同
  9. 方方格子补丁_方方格子wps版下载 方方格子Excel工具箱插件(WPS版全套) v3.2.8.0 中文官方安装版 下载-脚本之家...
  10. 40个好用的Unity游戏开发插件大合集
  11. java中的jQuery与Ajax的应用,菜鸟教程
  12. 扫描微信小程序体验版二维码无法打开
  13. 融资买入:连续10天、7天
  14. python3集合_python3集合练习(set)
  15. 6.哈夫曼树及哈夫曼编码
  16. 四 . LeetCode标签刷题——树/二叉树(一) 算法部分
  17. 22-07-14 西安 Git 分布式版本控制系统 、代码管理
  18. spring源码分析04-spring循环依赖底层源码解析
  19. 黄淮学院CSDN高校俱乐部把梳子卖给和尚话剧表演活动
  20. 史上最详细店铺运营方案,新手必看!

热门文章

  1. Ubuntu创建文件/目录和vim
  2. 六一节目《 少年中国说》
  3. 点击咨询弹出扣扣;聊天对话框
  4. 2019年浙江高考数学真题(填空题1-5题)解析答案
  5. Linux中设置FTP服务的权限
  6. 带你走进整个游戏行业《下》
  7. Integer类中的valueOf方法
  8. 第2章 SSD主控和全闪存阵列
  9. Spring+Vue房屋租赁租房系统
  10. 百度移动搜索自动转码太坑爹,JS跳转地址会被抓取