Elasticsearch 7.x 版本移除 type 后多类型数据怎么存储?

文章导读
Elasticsearch 7.x 彻底移除了 mapping type 概念,每个索引只能有一个类型,处理多类型数据最稳妥的方案是按业务拆分成多个索引,或在文档内增加字段区分。
📋 目录
  1. 快速处理思路
  2. 为什么会这样
  3. 分步处理
  4. 怎么验证是否生效
  5. 常见坑
  6. 参考来源
A A

Elasticsearch 7.x 彻底移除了 mapping type 概念,每个索引只能有一个类型,处理多类型数据最稳妥的方案是按业务拆分成多个索引,或在文档内增加字段区分。

先说结论:升级 7.x 后不再支持单索引多类型,建议按业务模型拆分索引或使用字段区分。

  • 适合:新业务直接单类型单索引,旧业务迁移需重新规划映射
  • 先准备:统计现有 type 使用情况,评估 reindex 成本
  • 验收:确认写入不带 type 参数,查询改用 term 过滤

快速处理思路

既然不能用 type 区分,就需要在索引结构或文档内容上做调整。以下是两种常见模式的映射定义示例。

方案一:拆分索引(推荐)

不同业务实体使用不同索引,例如用户和商品分开存储。

PUT /users
{
  "mappings": {
    "properties": {
      "name": { "type": "keyword" }
    }
  }
}

方案二:单索引加字段区分

在同一索引中增加一个 keyword 类型字段来标记逻辑类型。

PUT /my_index
{
  "mappings": {
    "properties": {
      "doc_type": { "type": "keyword" },
      "content": { "type": "text" }
    }
  }
}

为什么会这样

在 6.x 及更早版本中,一个索引可以包含多个 type,但这带来了底层存储的复杂性。不同 type 下同名但类型不同的字段会导致 Lucene 底层存储冲突,影响性能且难以维护。7.x 移除 type 是为了简化模型,避免字段命名冲突,并提升查询效率。

Elasticsearch 7.x 版本移除 type 后多类型数据怎么存储?

分步处理

1. 评估现有数据

检查 6.x 集群中哪些索引使用了多个 type。使用 mapping API 查看结构。

GET /old_index/_mapping

2. 设计新映射

根据业务关系决定是拆索引还是加字段。如果数据关联性强且查询常跨类型,加字段可能更方便;如果业务隔离明显,拆索引更清晰。

3. 执行 Reindex

使用 _reindex API 将旧数据迁移到新结构。注意在迁移过程中转换文档结构,移除 type 依赖。以下是从 6.x 迁移到 7.x 的标准请求示例,包含脚本处理类型字段:

POST _reindex
{
  "source": {
    "index": "old_index_6x",
    "type": "old_type"
  },
  "dest": {
    "index": "new_index_7x"
  },
  "script": {
    "source": "ctx._source.doc_type = params.type; ctx.remove('_type');",
    "params": { "type": "user" }
  }
}

4. 更新应用代码

Elasticsearch 7.x 版本移除 type 后多类型数据怎么存储?

修改写入逻辑,不再指定 type 参数;修改查询逻辑,使用 term 查询替代 type 过滤。以下是客户端代码修改前后对比:

// Java High Level Client 旧写法 (6.x)
IndexRequest request = new IndexRequest("index", "type", "id");

// Java High Level Client 新写法 (7.x+)
IndexRequest request = new IndexRequest("index").id("id");

怎么验证是否生效

1. 使用 GET /<index>/_mapping 确认映射中不再包含 type 层级。

2. 尝试写入一条不带 type 参数的文档,确认不报错。

3. 执行查询,确保原本通过 type 过滤的数据现在能通过新字段或索引名正确返回。以下是查询 DSL 改造对比:

// 6.x 旧写法 (type 查询)
{
  "query": {
    "type": { "value": "user" }
  }
}

// 7.x 新写法 (term 查询替代)
{
  "query": {
    "term": { "doc_type": "user" }
  }
}

常见坑

1. 字段冲突:6.x 中不同 type 可以有同名字段但不同类型,7.x 不允许。迁移前必须合并冲突字段。

2. 代码硬编码:部分客户端库可能在 URL 中硬编码了 type 名称,升级后需移除。

3. 别名管理:如果之前用别名配合 type 使用,迁移后需要调整别名指向新的索引结构。

参考来源

  • Elasticsearch 官方文档 - Removal of mapping types: https://www.elastic.co/guide/en/elasticsearch/reference/7.17/removal-of-types.html