0%

ElasticSearch-Update By Query & Reindex API

⼀般在以下⼏种情况时,我们需要重建索引:

  • 索引的 Mappings 发⽣变更:字段类型更改,分词器及字典更新
  • 索引的 Settings 发⽣变更:索引的主分⽚数发⽣改变
  • 集群内,集群间需要做数据迁移

Elasticsearch 提供如下两种内置 API 可实现上述索引重建:

  • Update By Query:在现有索引上重建
  • Reindex:在其他索引上重建索引

1. Update By Query

相关阅读:https://www.elastic.co/guide/en/elasticsearch/reference/7.4/docs-update-by-query.html

ES 支持对 mapping 修改增加子字段,比如下述文档中对 content 字段增加 text 类型的子字段 english,并指定英文分词器:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
PUT blogs/_mapping
{
"properties": {
"content": {
"type": "text",
"fields": {
"english": {
"type": "text",
"analyzer": "english"
}
}
}
}
}

默认情况下,采用上述更新之前已经存入的文档并不存在子字段 english 的相关定义(当然更新之后加入的文档没有此问题)。例如在做上述更新之前已经通过如下语句添加了一篇文档:

1
2
3
4
5
PUT blogs/_doc/1
{
"content":"Hadoop is cool",
"keyword":"hadoop"
}

因此下面通过子字段去查询时,是无法查询到相关信息的。

1
2
3
4
5
6
7
8
POST blogs/_search
{
"query": {
"match": {
"content.english": "Hadoop"
}
}
}

为了解决这种问题,可以使用如下 _update_by_query 来同步 mapping 上的更新到所有文档上。再次使用上述查询语句我们便能查询到相关文档信息:

1
2
3
POST blogs/_update_by_query
{
}

2. Reindex

相关阅读:https://www.elastic.co/guide/en/elasticsearch/reference/7.4/docs-reindex.html

由于 ES 不允许在原有 Mapping 上对字段类型进⾏修改,因此只能创建新的索引,并且设定正确的字段类型,再重新导⼊数据。

Reindex API ⽀持把⽂档从⼀个索引拷⻉到另外⼀个索引,在如下的一些场景可以使用 Reindex API:

  • 修改索引的主分⽚数
  • 改变字段的 Mapping 中的字段类型
  • 集群内数据迁移 / 跨集群的数据迁移

需要注意的是使用 reindex 进行字段类型变更到操作时,需要先自行创建新索引的 mapping 后在进行 reindex。例如下面新建索引 blogs_fix 及其 mapping,不同于 blogs 索引,keyword 字段没有子字段,而是只定义其类型。我们使用 reindex 实现将 blogs 中的数据导入的 blogs_fix 中并以新的 mapping 来存储数据:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
PUT blogs_fix
{
"mappings": {
"properties": {
"content": {
"type": "text",
"fields": {
"english": {
"type": "text",
"analyzer": "english"
}
}
},
"keyword": {
"type": "keyword"
}
}
}
}

POST _reindex
{
"source": {
"index": "blogs"
},
"dest": {
"index": "blogs_fix"
}
}

另外,可以通过指定 op_type 参数值为 create 来控制 reindex 只对未创建的目标索引有效。当 dest 指定的索引已经存在数据时,不支持使用 reindex 。

------ 本文结束------