笔者在用 curl 命令行对 ElasticSearch 进行文档插入时,报了如下错误。

[estestuser@vm-10-201-42-9 ~]$ curl -u elastic -H "Content-Type: application/json" -XPOST 'http://localhost:9200/testindex/5?pretty' -d '{"mchnt_id" : "5"}'
Enter host password for user 'elastic':
{
  "error" : {
    "root_cause" : [
      {
        "type" : "illegal_argument_exception",
        "reason" : "Rejecting mapping update to [testindex] as the final mapping would have more than 1 type: [_doc, 5]"
      }
    ],
    "type" : "illegal_argument_exception",
    "reason" : "Rejecting mapping update to [testindex] as the final mapping would have more than 1 type: [_doc, 5]"
  },
  "status" : 400
}

  其中,testindex 为 ElasticSearch 的索引,文档 ID 为 5,在插入文档时,报错:Rejecting mapping update to [testindex] as the final mapping would have more than 1 type: [_doc, 5]。测试环境使用的是 7.1.1 版本的 ElasticSearch,经查阅,原因是 Elasticsearch 在 7.x 版本中已经去除 type 的概念。

  type 的版本迭代:

  • 5.x 及以前版本,一个 index 有一个或者多个 type
  • 6.x 版本,一个 index 只有一个 type
  • 7.x 版本移除了 type,type 相关的所有内容全部变成 Deprecated,为了兼容升级和过渡,所有的 7.x 版本 es 数据写入后 type 字段都默认被置为 “_doc”
  • 8.x 版本完全废弃 type

  下图是 ElasticSearch 官网上关于 type 的演进历程。
在这里插入图片描述
  1、为何要去除 type 的概念?

  因为 Elasticsearch 设计初期,是直接参考了关系型数据库的设计模式,存在了 type(数据表)的概念。
  在关系型数据库里,table 是相互独立的,一个 table 里的 column 和另外一个 table 的同名 column 没有关系,互不影响。但在 type 里字段却不是这样的,在一个 Elasticsearch 的 index 里,所有不同 type 的同名 field 内部使用的是同一个 lucene 字段存储。举例来说,teacher 类型的 user_name 字段和 student 类型的 user_name 字段是存储在一个 field 里的,两个 type 里的 user_name 必须有一样的 field 定义。
  这可能导致一些问题,例如你希望同一个索引中 “create_time” 字段在一个类型里是存储日期值,在另外一个类型里存储字符串。另外,按照 Lucene 存储的方式和特点,如果按照此种方式组织数据,会影响到底层的压缩比例和存储效率。
  Lucene 的全文检索功能之所以快,是因为 “倒序索引” 的存在。而这种倒序索引的生成是基于 index 的,而非 type。多个 type 反而会减慢搜索的速度。为了保持 Elasticsearch “一切为了搜索” 的宗旨,适当的做些改变(去除 type)也是无可厚非的,也是值得的。

  2、为何不是在 6.X 版本开始就直接去除 type,而是要逐步去除 type?

  因为历史原因,前期 Elasticsearch 支持一个 index 下存在多个 type,而且有很多项目在使用 Elasticsearch 作为数据库。如果直接去除 type 的概念,不仅使很多应用了 Elasticsearch 的项目将面临业务、功能和代码的大改,而且对于 Elasticsearch 官方来说,也是一个巨大的挑战,很多涉及到 type 的源码都要修改。

  综上所述,本次报错的 ES 插入语句修改如下,即解决问题,成功插入一条文档。

[estestuser@vm-10-201-42-19 ~]$ curl -u elastic -H "Content-Type: application/json" -XPOST 'http://localhost:9200/testindex/_doc/5?pretty' -d '{"mchnt_id": "5"}'
Enter host password for user 'elastic':
{
  "_index" : "testindex",
  "_type" : "_doc",
  "_id" : "5",
  "_version" : 1,
  "result" : "created",
  "_shards" : {
    "total" : 2,
    "successful" : 2,
    "failed" : 0
  },
  "_seq_no" : 0,
  "_primary_term" : 5
}
文章参考:
Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐