The mapping definition cannot be nested under a type [_doc] unless include_type_name is set to true 的解决方法

背景

自己在本地开发在 ElasticSearch 6.4 版本上创建索引是正常的,但是上传到服务器同样的命令创建索引却提示

{
    "error": {
        "root_cause": [{
            "type": "illegal_argument_exception",
            "reason": "The mapping definition cannot be nested under a type [_doc] unless include_type_name is set to true."
        }],
        "type": "illegal_argument_exception",
        "reason": "The mapping definition cannot be nested under a type [_doc] unless include_type_name is set to true."
    },
    "status": 400
}
将其中的错误原因 “The mapping definition cannot be nested under a type [doc] unless includetypename is set to true”
翻译成中文就是:在 mapping 定义中 doc 类型下面不能被嵌套,如果要嵌套的话,必须将 includetypename 参数设置为 True

问题成因

  • 经过排查,本地环境和线上环境安装的 ElasticSearch 的版本不一致,线上环境是最近安装的,是最新的 ElasticSearch 7 的版本,而本地因为历史原因还是使用的 ElasticSearch 6 的旧版本。正是因为版本不一致的问题,导致了本地能够正常运行的代码到了线上却报以上错误。
  • 另外 include_type_name 在 ElasticSearch 6 版本和 7 版本中的默认设置是不同的,所以就导致了版本不同执行结果不同

解决方法

  • 其实错误提示已经给出了解决方法,将 mapping 设置中的 include_type_name 设置为 True 后再次执行索引的创建就可以
  • 尽量保证线上线下执行环境的一致性,避免类似问题的重复产生

具体代码

将具体代码中新增 include_type_name 为 true (PHP)参数,注意 include_type_name 添加位置,是和 index 和 body 平级,不是在 body 下一级。

$this->es->indices()->create([
            'index' => 'index_0',
            'body'  => [
                'settings' => $indexClass::getSettings(),
                'mappings' => [
                    '_doc' => [
                        'properties' => $indexClass::getProperties(),
                    ],
                ],
                'aliases'  => [
                    $aliasName => new \stdClass(),
                ],
            ],
        ]);

以上是修改前的代码

$this->es->indices()->create([
            'index' => 'index_0',
            'body'  => [
                'settings' => $indexClass::getSettings(),
                'mappings' => [
                    '_doc' => [
                        'properties' => $indexClass::getProperties(),
                    ],
                ],
                'aliases'  => [
                    $aliasName => new \stdClass(),
                ],
            ],
            'include_type_name' => true,
        ]);

修改后的代码,只增加了最后一行 'include_type_name' => true


相关 ElasticSearch 课程: 极客时间《Elasticsearch 核心技术与实战》作者是阮一鸣 eBay Pronto 平台技术负责人