Mapping,映射,相当于关系型数据库创建语句,定义文档字段及其类型、索引与存储方式。通常会涉及如下方面:
文档中哪些字段需要定义成全文索引字段。
文档中哪些字段定义为精确值,例如日期,数字、地理位置等。
文档中哪些字段需要被索引(能通过该字段的值查询文档)。
日期值的格式。
动态添加字段的规则定义等。
1、类型映射概述
1.1 映射类型
Elasticsearch支持meta-fields、fields or properties两种映射类型,将决定文档的索引方式。
Meta-fields
元数据字段用于定义文档的元数据字段的特征,文档的元数据字段主要包括_index、_type、_id、_source这4个字段。
Fields or properties
属性字段列表,通过properties字段定义整个文档有效载荷的各字段的数据类型、分词器等属性。
映射类型,可以理解为以何种方式来定义索引中一个类型的字段集。
1.2 数据类型
每一个字段都会指定一个数据类型,数据类型通常如下:
简单类型,例如text、keyword、date、long、double、boolean、ip
复合类型,诸如object(json)、netsed.
特殊类型,诸如geo_point、geo_shape(地图相关类型)、completion。
后续章节会单独重点剖析elasticsearch所支持的数据类型。
1.3 映射保护机制
es提供如下参数来限制es的行为:
index.mapping.total_fields.limit t
索引中允许定义的最大字段(属性)个数,默认为1000。
index.mapping.depth.limit
字段级联的最大深度,默认为20。
index.mapping.nested_fields.limit
一个索引最多包含字段类型为nested的个数,默认为50。
1.4 动态映射机制
与关系型数据库不同的是,一个type(对应关系型数据库的表)中的字段可以在使用过程中动态添加。具体的动态映射机制。
==============================================================================================================================
Dynamic Mapping
1.1 什么是动态映射
动态映射时Elasticsearch的一个重要特性: 不需要提前创建iindex、定义mapping信息和type类型, 你可以 直接向ES中插入文档数据时, ES会根据每个新field可能的数据类型, 自动为其配置type等mapping信息, 这个过程就是动态映射(dynamic mapping).
Elasticsearch动态映射的示例:
字段内容(field)映射的字段类型(type)
true | false
boolean
1234
long
123.4
float
2018-10-10
date
"hello world"
text
说明: 动态映射虽然方便, 可并不直观, 为了个性化自定义相关设置, 可以在添加文档之前, 先创建index和type, 并配置type对应的mapping, 以取代动态映射.
(写入文档的时候,索引不存在,会自动创建索引, 无需手动创建,ES会根据内容推断字段的类型,推断会不准确,可能造成某些功能无法使用,例如 范围查询。)
1.2 体验动态映射
(1) 插入如下数据:
如果已有website索引, 先删除DELETE blog , 再执行下面的插入操作: .
PUT blog/_doc/1
{
"blog_id": 10001,
"author_id": 5520,
"post_date": "2018-01-01",
"title": "my first blog",
"content": "my first blog in the website"
}
PUT blog/_doc/2
{
"blog_id": 10002,
"author_id": 5520,
"post_date": "2018-01-02",
"title": "my second blog",
"content": "my second blog in the website"
}
PUT blog/_doc/3
{
"blog_id": 10003,
"author_id": 5520,
"post_date": "2018-01-03",
"title": "my third blog",
"content": "my third blog in the website"
}
(2) 进行如下检索测试:
注意这里结果数是3的情况.
GET blog/_search?q=2018 // 1条结果, 5.6之前的版本是3条结果
GET blog/_search?q=2018-01-01 // 1条结果, 5.6之前的版本是3条结果
GET blog/_search?q=post_date:2018 // 1条结果
GET blog/_search?q=post_date:2018-01-01// 1条结果
(3) 查看ES自动建立的mapping:
GET blog/_mapping
// 结果如下:
{
"blog" : { // index是blog
"mappings" : {
"_doc" : { // type是_doc - 方便后期升级版本
"properties" : {
"author_id" : {
"type" : "long"
},
"blog_id" : {
"type" : "long"
},
"content" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"post_date" : {
"type" : "date" // 日期"2018-01-01"被自动识别为date类型
},
"title" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
}
}
}
}
}
}
1.3 搜索结果不一致的原因分析
如果使用的是ES 5.6.x之前的版本, [1.2]节中搜索结果会不一致, 这是因为:
ES自动建立mapping时, 为不同的field映射了不同的数据类型, 而不同数据类型在分词、搜索等行为上也是不同的.
我们通过q=xxx的方式搜索, 底层是从每个文档的_all字段中进行匹配的 —— ES默认将每个文档的所有field的值抽取到一个名为_all的元字段中.
官方文档指出, 从6.0+版本开始, _all字段就被禁止使用了, 建议我们使用copy_to实现相似的功能.—— 也就是说, 如果_all字段被关闭, 就不会出现搜索结果不一致的情况.
(1) GET website/blog/_search?q=2018
id=1的文档的_all的值为:
2018-01-01 my first blog my first blog in the website 5520
说明: _all字段将所有的值作为字符串索引, 所以日期被索引为年、月、日三个值, _all字段的倒排索引结果如下:
doc1doc2Doc3
2018
*
*
*
01
*
*
*
02
*
03
*
此项搜索中, ES是从_all字段中检索, 3个文档中都有 2018 , 所以结果数是3.
(2) GET website/blog/?q=2018-01-01
同(1), ES也是从_all字段中检索, 结果数同样是3.
(3) GET website/blog/_search?q=post_date:2018-01-01
此检索指定了检索条件, ES将从post_date字段中检索, 而post_date被映射为date类型, 所以将进行精确匹配.
而date类型的字段索引的内容有其默认的固定格式. post_date字段的倒排索引结果如下:
doc1doc2doc3
2018-01-01 00:00:00 UTC
*
2018-01-02 00:00:00 UTC
*
2018-01-03 00:00:00 UTC
*
可以看出, 满足条件的只有1个结果, 即doc1.
(4) GET /_search?q=post_date:2018
这是ES 5.x版本中做的一个优化, 搜索post_date:01等是不会出现结果的, 搜索2018会出现第一条结果.
2 开启dynamic mapping动态映射策略
新增字段
dynamic设置为true,一旦有新增字段的文档写入,mapping也同时被更新。
dynamic设置为false,mapping不会被更新,新增的字段数据无法被索引,但是信息会出现在source中.
dynamic设置为strict,文档写入失败
已有的字段,一旦有数据写入,不支持修改(倒排索引不支持修改)
希望更改字段类型,用Reindex API,重建索引
设计原因
如果修改字段数据类型,会导致已经被索引的文档不能被搜索。
新增字段不存在影响。
2.1 约束策略
策略功能说明
true
开启 —— 遇到陌生字段时, 进行动态映射
false
关闭 —— 忽略遇到的陌生字段
strict
遇到陌生字段时, 作报错处理
2.2 策略示例
(1) 使用不同的约束策略:
PUT blog_user
{
"mappings": {
"_doc": {
"dynamic": "strict",// 严格控制策略
"properties": {
"name": { "type": "text" },
"address": {
"type": "object",
"dynamic": "true"// 开启动态映射策略
}
}
}
}
}
(2) 插入数据演示:
// 插入数据时多添加一个字段
PUT blog_user/1
{
"name": "shou feng",
"content": "this is my blog", // 多添加的字段
"address": {
"province": "guangdong",
"city": "guangzhou"
}
}
将抛出如下错误信息:
{
"error": {
"root_cause": [
{
"type": "strict_dynamic_mapping_exception",
// 错误原因: 不允许动态添加field
"reason": "mapping set to strict, dynamic introduction of [content] within [_doc] is not allowed"
}
],
"type": "strict_dynamic_mapping_exception",
"reason": "mapping set to strict, dynamic introduction of [content] within [_doc] is not allowed"
},
"status": 400
}
添加符合约束的数据, 操作就能成功:
PUT blog_user/_doc/1
{
"name": "shou feng",
"address": {
"province": "guangdong",
"city": "guangzhou"
}
}
(3) 查看映射信息:
GET user/_mapping
// 映射信息如下:
{
"blog_user" : {
"mappings" : {
"_doc" : {
"dynamic" : "strict", // 严格约束条件
"properties" : {
"address" : {
"dynamic" : "true", // 开启动态映射策略
"properties" : {
"city" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"province" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
}
}
},
"name" : {
"type" : "text"
}
}
}
}
}
}
3 定制dynamic mapping策略
3.1 date_detection - 日期识别策略
对于date类型的数据, Elasticsearch有其默认的识别策略, 比如"yyyy-MM-dd". 存在这种情况:
① 第一次添加文档时, 某个field是类似"2018-01-01"的值, 其类型就动态映射成date;
② 后期再次添加文档, 该field是类似"hello world"的值, ES就会因为类型不匹配而报错.
为解决这一问题, 可以手动关闭某个type的date_detection; 如果不需要关闭, 建议手动指定这个field为date类型. 示例如下:
PUT blog_user/_mapping/_doc
{
"date_detection": false
}
3.2 在type中自定义动态映射模板
(1) 在type中定义动态映射模板(dynamic mapping template) —— 把所有的String类型映射成text和keyword类型:
先删除已有的blog_user索引: DELETE blog_user, 再执行下述命令:
PUT blog_user
{
"mappings": {
"_doc": {
"dynamic_templates": [
{
"en": { // 动态模板的名称
"match": "*_en", // 匹配名为"*_en"的field
"match_mapping_type": "string",
"mapping": {
"type": "text", // 把所有的string类型, 映射成text类型
"analyzer": "english", // 使用english分词器
"fields": {
"raw": {
"type": "keyword",
"ignore_above": 256
}
}
}
}
}
]
}
}
}
(2) 添加数据:
PUT blog_user/_doc/1
{
"name": "the first register user"
}
PUT blog_user/_doc/2
{
"name_en": "the second register user"
}
(3) 检索数据:
// 有结果: "name"没有匹配到任何动态模板, 默认使用standard分词器
GET blog_user/_search
{
"query": {
"match": {"name": "the"}
}
}
// 无结果: "name_en"匹配到了动态模板, 使用english分词器, the是停用词, 被过滤掉了
GET blog_user/_search
{
"query": {
"match": {"name_en": "the"}
}
}
说明:
这里的match_mapping_type的类型支持 [object, string, long, double, boolean, date, binary], 若使用text将抛出如下错误信息:
{
"error": {
"root_cause": [
{
"type": "mapper_parsing_exception",
"reason": "Failed to parse mapping [_doc]: No field type matched on [text], possible values are [object, string, long, double, boolean, date, binary]"
}
],
"type": "mapper_parsing_exception",
"reason": "Failed to parse mapping [_doc]: No field type matched on [text], possible values are [object, string, long, double, boolean, date, binary]",
"caused_by": {
"type": "illegal_argument_exception",
"reason": "No field type matched on [text], possible values are [object, string, long, double, boolean, date, binary]"
}
},
"status": 400
}
在6.0之前的版本, 将抛出如下过期的警告信息:
Deprecation: match_mapping_type [text] is invalid and will be ignored:
No field type matched on [text], possible values are [object, string, long, double, boolean, date, binary]
3.3 [过期]在index中自定义默认映射模板
_default mapping - 默认映射模板是类似于全局变量的存在, 对当前配置的索引起作用.
默认映射模板在Elasticsearch 6.x版本中已经不再支持, 因为6.0版本开始, 每个索引只能有一个类型, 因此默认模板没有存在的意义了.
下面的演示过程, 是在6.0之前的版本上的测试.
(1) 在index中定义默认映射模板(default mapping template):
先删除已有的blog_user索引: DELETE blog_user, 再执行下述命令:
PUT blog_user
{
"mappings": {
"_default_": {
"_all": { "enabled": false }
},
"_doc": {
"_all": { "enabled": true }
}
}
}
(2) 动态映射可以和索引模板(Index Templates)配合使用.
无论是自动创建Index, 还是手动显式创建Index, 索引模板都可以用来配置新索引的默认mappings(映射)、settings(配置项)和aliases(别名). 具体使用方法请参考博客: ES 10 - 如何使用Elasticsearch的索引模板(index template)
4. 显示的设置mapping信息
显示的设置mapping可以更灵活控制ES。
根据API手册,手写,减少出错概率的方法。
创建一个临时的index,写入一些样本数据
通过mapping api获得该临时文件的动态mapping定义
修改后用,使用该配置创建索引
删除临时索引
4.1 控制字段是否被index
index的选项配置
docs:记录doc id
freqs:记录doc id和term的频次
position: 记录doc id、term频次、term位置
offsets:doc id、term频次、term位置、字符串的偏移量
text类型默认是positions,其他的默认为docs,记录内容越多,占据空间越大
例如创建mapping,字段名为user_name,字符串类型。不需要索引,info字段的倒排索引类型为positions。
PUT mapping_test3
{"mappings": {"properties": {"user_name":{"index": false,"type": "text"},"info":{"index_options": "positions","type": "text"}
}
}
}
4.2 null_value
对Null值进行搜索,可以通过keyword类型的字段设置null_value。
就可以对NULL搜索:GET users/_search?q=mobile:NULL
4.3 copy_to
用来满足一些搜索需要,类似于数据库 title like "%a%" or title2 like "%a%"
copy_to的字段不会出现在_source里面
PUT users
{"mappings": {"properties": {"first_name":{"type": "text","copy_to": "full_name"},"last_name":{"type": "text","copy_to": "full_name"}
}
}
}
就可以在支持 :GET users/_search?q=full_name:(zhang san)搜索。
==============================================================================================================================
1.5 更新已有映射定义
es不支持直接修改已索引的已存在的字段映射,因为修改字段映射,意味着已索引的数据生效,可以使用别名机制来修改字段的名称,如果需要修改已存在字段的映射,建议重新创建一个索引,再使用reindex API迁移数据。
1.6 索引、type组织方式
index、type的定义
Index是什么 :Index 存储在多个分片中,其中每一个分片都是一个独立的 Lucene Index。这就应该能提醒你,添加新 index 应该有个限度:每个 Lucene Index 都需要消耗一些磁盘,内存和文件描述符。因此,一个大的 index 比多个小 index 效率更高:Lucene Index 的固定开销被摊分到更多文档上了。
另一个重要因素是你准备怎么搜索你的数据。在搜索时,每个分片都需要搜索一次, 然后 ES 会合并来自所有分片的结果。例如,你要搜索 10 个 index,每个 index 有 5 个分片,那么协调这次搜索的节点就需要合并 5x10=50 个分片的结果。这也是一个你需要注意的地方:如果有太多分片的结果需要合并,或者你发起了一个结果巨大的搜索请求,合并任务会需要大量 CPU 和内存资源。这是第二个让 index 少一些的理由。
type 是什么:使用 type 允许我们在一个 index 里存储多种类型的数据,这样就可以减少 index 的数量了。在使用时,向每个文档加入 _type 字段,在指定 type 搜索时就会被用于过滤。使用 type 的一个好处是,搜索一个 index 下的多个 type,和只搜索一个 type 相比没有额外的开销 —— 需要合并结果的分片数量是一样的。
但是,这也是有限制的:
不同 type 里的字段需要保持一致。例如,一个 index 下的不同 type 里有两个名字相同的字段,他们的类型(string, date 等等)和配置也必须相同。
只在某个 type 里存在的字段,在其他没有该字段的 type 中也会消耗资源。这是 Lucene Index 带来的常见问题:它不喜欢稀疏。由于连续文档之间的差异太大,稀疏的 posting list 的压缩效率不高。这个问题在 doc value 上更为严重:为了提高速度,doc value 通常会为每个文档预留一个固定大小的空间,以便文档可以被高速检索。这意味着,如果 Lucene 确定它需要一个字节来存储某个数字类型的字段,它同样会给没有这个字段的文档预留一个字节。未来版本的 ES 会在这方面做一些改进,但是我仍然建议你在建模的时候尽量避免稀疏。[1]
得分是由 index 内的统计数据来决定的。也就是说,一个 type 中的文档会影响另一个 type 中的文档的得分。
这意味着,只有同一个 index 的中的 type 都有类似的映射 (mapping) 时,才应该使用 type。否则,使用多个 type 可能比使用多个 index 消耗的资源更多。
索引在创建时,Elasticsearch6.x版本只支持一个映射类型,而7.x版本后将完成删除映射类型。es5.x中一个索引包含多个type的情况再6.x版本将继续支持查询,7.0版本后,API将完成移除与多类型相关的API。
Elasticsearch6.x版本后为什么不继续对单一索引库提供多类型支持呢?
当初,为了方便理解es,通常与关系型数据库进行类比,例如es中的index(索引)相当于关系型数据库的database,而类型(type)相当于关系型数据库中的table。其实这是一个错误的比喻。在关系型数据库中,表是相互独立的,一个表中的列名与另外一个表中的列名相同是没有关系的,但对于es的类型映射定义,情况并非如此。
在es单一索引中,不同映射类型(type)具有相同名称的字段在内部都是由同一个Lucence字段来存储,这也就意味着同一个索引内不同的类型,如果出现名字相同的字段,其数据类型也必须相同。更重要的是,存储在同一索引中具有很少或没有共同字段的不同类型(实体)会导致数据稀疏,大大降低Lucece高效压缩文档的能力,影响其检索性能。
基于上述各种原因,故es将在后续版本中不支持一个索引中定义多个类型。
2、meta-field(元字段)
每个文档都有与之关联的元数据,例如_index、mapping _type和_id元字段。在创建映射类型时,可以定制其中一些元字段的行为。
identity meta-fields(表明文档身份的元字段)
_index
文档所在的索引,类似于关系型数据库的database。
_uid
_type与_id的组合,文档的唯一标识。
_type
文档映射类型。
_id
文档的_id值。
document source meta-fields
_source
文档的原始json数据。
_size
文档_souce字段的字节长度,需要插件:mapper-size plugin。
indexing meta-fields
_all
将所有字段映射成一个_all字段,在6.0.0版本后废弃,可以使用copy_to来定义需要聚合的字段。
_field_names
_field_names字段,用于索引文档中包含除null之外的任何值的每个字段的名称。exist查询使用这个字段来查找对于特定字段具有或不具有任何非空值的文档,也就是该字段记录的是字段值不为null的所有字段名称。当前版本,_field_names字段不包含启用了doc_values、norm的字段,对于启用doc_values或norm的字段,exist查询仍然可用,但不会使用_field_names字段。
注:禁用_field_names通常是不必要的,因为它不再承载以前的索引开销。如果你有很多禁用doc_value和norm的字段,并且你不需要使用这些字段执行exist查询,你可能想禁用_field_names,你可以通过如下方式禁用_field_names字段:
PUT tweets
{"mappings": {"_doc": {"_field_names": {"enabled": false}
}
}
}
_ignored
设置为ignore_malformed=true的所有字段。
routing meta-field
_routing
分片路由字段。
other meta-field
1._meta
用于用户自定义的元数据,例如:
PUT my_index
{"mappings": {"_doc": {"_meta": {"class": "MyApp::User","version": {"min": "1.0","max": "1.3"}
}
}
}
}
本文初步介绍了Elasticsearch 类型映射与元字段类型,后续文章将介绍映射参数、elasticsearch支持的数据类型、自动类型映射机制等。
3、映射类型(mapping type)从Elasticsearch中移除
注意:在Elasticsearch6.0.0或者或者更新版本中创建的索引只会包含一个映射类型(mapping type)。在5.x中创建的具有多个映射类型的索引在Elasticsearch6.x中依然会正常工作。在Elasticsearch7.0.0中,映射类型将会被完全移除。
什么是映射类型?
从Elasticsearch的第一个发行版开始,每一个文档都会被存储在一个单独的索引中,并且配以一个单独的映射类型。一个映射类型被用来表示被索引的文档或者实体的类型,比如一个twitter索引可能会有一个user类型和一个tweet类型。
每一个映射类型都可以有其自身的字段,所以user类型可能有一个full_name字段,一个user_name字段和一个email字段,而tweet类型可能会包含一个content字段,一个tweeted_at字段,以及与user类型中类似的user_name字段。
每个文档都有一个_type元字段用来保存类型名,搜索可以通过在URL中指定类型名将搜索限定于一个或多个类型中:
GET twitter/user,tweet/_search
{
"query": {
"match": {
"user_name": "kimchy"
}
}
}
_type字段的值会与文档的_id字段的值组合起来生成_uid字段,所以具有相同_id的不同类型的多个文档可以共存于一个索引中。
映射类型也被用来建立文档之间的父子关系,比如question类型的文档可以是answer类型文档的父亲。
为什么要移除映射类型(mapping types)
开始的时候,我们说“索引(index)”类似于SQL数据库中的“数据库”,将“类型(type)”等同于“表”。
这是一个糟糕的类比,并且导致了一些错误的假设。在SQL数据库中,表之间是相互独立的。一个表中的各列并不会影响到其它表中的同名的列。而在映射类型(mappingtype)中却不是这样的。
在同一个Elasticsearch索引中,其中不同映射类型中的同名字段在内部是由同一个Lucene字段来支持的。换句话说,使用上面的例子,user类型中的user_name字段与tweet类型中的user_name字段是完全一样的,并且两个user_name字段在两个类型中必须具有相同的映射(定义)。
这会在某些情况下导致一些混乱,比如,在同一个索引中,当你想在其中的一个类型中将deleted字段作为date类型,而在另一个类型中将其作为boolean字段。
在此之上需要考虑一点,如果同一个索引中存储的各个实体如果只有很少或者根本没有同样的字段,这种情况会导致稀疏数据,并且会影响到Lucene的高效压缩数据的能力。
基于这些原因,将映射类型的概念从Elasticsearch中移除。
映射类型的可选替代方案
每种文档类型一个索引
第一种选择就是每个文档类型对应一个索引。你可以不将tweets和users存储于同一个索引,而将它们分别存储于tweets索引和users索引中。索引之间是完全相互独立的,不同索引中的(同名的)字段类型也就不会产生冲突了。
这种方式有两个好处:
数据更倾向于密集(而不是稀疏),这样就能获益于Lucene的压缩技术。
因为同一个索引中的所有的文档代表同一种实体,用于为全文搜索打分的条件统计会更精确。
每个索引可以依据其可能的文档存储量级来设置相关的配置:可以对users使用较少的主分片,同时对tweets使用较大数量的主分片。
自定义类型字段
当然,一个集群中可以创建的主分片的数量是有限制的,所以你可能不想为一个只有几千个文档的集合去浪费一整个分片。这种情况下你可以使用你自己定义的type字段,它看起来和原来的_type工作机制类似。
我们继续使用上面的user/tweet例子。原来的工作流程可能像下面这样:
PUT twitter
{"mappings": {"user": {"properties": {"name": { "type": "text"},"user_name": { "type": "keyword"},"email": { "type": "keyword"}
}
},"tweet": {"properties": {"content": { "type": "text"},"user_name": { "type": "keyword"},"tweeted_at": { "type": "date"}
}
}
}
}
PUT twitter/user/kimchy
{"name": "Shay Banon","user_name": "kimchy","email": "[email protected]"}
PUT twitter/tweet/1{"user_name": "kimchy","tweeted_at": "2017-10-24T09:00:00Z","content": "Types are going away"}
GET twitter/tweet/_search
{"query": {"match": {"user_name": "kimchy"}
}
}
映射类型的移除计划
对于用户来说这是一个大的变化,所以我们尽可能将这个过程变得平滑。这次变更的计划如下:
Elasticsearch 5.6.0
在一个索引上设置index.mapping.single_type:true会启用单索引-单一类型的行为,而这种行为在6.0中是强制的。
在5.6中创建的索引可以使用创建文档间父子关系的新的join字段。
Elasticsearch 6.x
5.x中创建的索引可以在6.x中正常工作
6.x中创建的索引只允许单个索引中存在单一的类型。任意的名字都可以作为类型,但是只能有一个。
_type名不再与_id组合生成_uid字段。_uid字段变成仅仅是_id字段的别名。
新创建的索引不再支持旧风格的父子关系,而应该使用join字段。
_default_映射类型被标记为不推荐使用。
Elasticsearch 7.x
URL中的type参数为可选。比如,索引一个文档不再要求提供文档类型。
GET|PUT_mapping API支持一个查询字符串参数(include_type_name),通过这个参数来指定请求体是否应该包含一个类型名的层。默认是true。7.x中没有显式指定类型的索引将会使用默认的_doc类型名。
_default_映射类型移除。
Elasticsearch 8.x
不再支持URL中的type参数。
include_type_name参数默认为false。
Elasticsearch 9.x
include_type_name参数移除。
将索引从多类型迁移到单类型
可以用ReindexAPI将多类型索引转化成单类型索引。下面的例子可以在Elasticsearch 5.6或者Elasticsearch6.x中使用。在6.x中,不必指定index.mapping.single_type,因为6.x中是默认开启的。
转:https://blog.csdn.net/prestigeding/article/details/84537296
参考:https://blog.csdn.net/cnweike/article/details/79223542
参考:https://www.jianshu.com/p/f1e5f0fde294