在Elasticsearch 7.0.0或更高版本中建立的索引再也不接受
_default_
映射,索引在6.x中建立将继续在Elasticsearch 6.x中运行,类型在api 7.0中是不受支持的,它会中断对索引建立、put映射、get映射、put模板、get模板和get字段映射API的更改。
自从第一次发布Elasticsearch以来,每一个文档都存储在一个索引中,并分配了一个映射类型,映射类型用于表示被索引的文档或实体的类型,例如twitter
索引可能具备user
类型和tweet
类型。数据库
每一个映射类型均可以有本身的字段,所以user
类型能够有full_name
字段、user_name
字段和email
字段,而tweet
类型能够有content
字段、tweeted_at
字段,和user
类型同样,还有user_name
字段。segmentfault
每一个文档都有一个包含类型名称的_type
元字段,经过在URL中指定类型名称,能够将搜索限制为一个或多个类型:api
GET twitter/user,tweet/_search { "query": { "match": { "user_name": "kimchy" } } }
_type
字段与文档的_id
相结合生成_uid
字段,所以具备相同_id
的不一样类型的文档能够存在于一个索引中。app
还使用映射类型在文档之间创建父子关系,所以类型为question
的文档能够是类型为answer
的文档的父文档。ui
最初,讨论了“索引”相似于SQL数据库中的“数据库”,以及“类型”等价于“表”。code
这是一个错误的类比,致使了错误的假设,在SQL数据库中,表是相互独立的,一个表中的列与另外一个表中具备相同名称的列没有关系,这与映射类型中的字段不一样。继承
在Elasticsearch索引中,不一样映射类型中具备相同名称的字段在内部由相同的Lucene字段支持,换句话说,使用上面的示例,user
类型中的user_name
字段存储在与tweet
类型中的user_name
字段彻底相同的字段中,并且两个user_name
字段在这两种类型中必须具备相同的映射(定义)。索引
例如,当你想要删除一个类型中的date
字段和同一个索引中的另外一个类型中的boolean
字段时,这可能会致使失败。ip
最重要的是,存储在同一索引中具备不多或没有共同字段的不一样实体会致使数据稀疏,并影响Lucene有效压缩文档的能力。文档
基于这些缘由,决定将映射类型的概念从Elasticsearch中移除。
第一种选择是为每一个文档类型都有一个索引,你能够将tweets
存储为tweets
和user
索引,而不是将tweets
和users
存储在单个twitter
索引中,索引之间是彻底独立的,所以索引之间不存在字段类型的冲突。
这种方法有两个好处:
每一个索引均可以根据它将包含的文档数量适当调整大小:你能够为users
使用较少的主碎片,而为tweet
使用较多的主碎片。
固然,集群中能够存在多少主碎片是有限制的,所以你可能不但愿为了一个只有几千个文档的集合而浪费整个碎片,在本例中,你能够实现本身的自定义类型字段,其工做方式与旧的_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": "shay@kimchy.com" } 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" } } }
你能够经过添加自定义类型字段来实现相同的功能,以下所示:
PUT twitter { "mappings": { "_doc": { "properties": { "type": { "type": "keyword" }, "name": { "type": "text" }, "user_name": { "type": "keyword" }, "email": { "type": "keyword" }, "content": { "type": "text" }, "tweeted_at": { "type": "date" } } } } } PUT twitter/_doc/user-kimchy { "type": "user", "name": "Shay Banon", "user_name": "kimchy", "email": "shay@kimchy.com" } PUT twitter/_doc/tweet-1 { "type": "tweet", "user_name": "kimchy", "tweeted_at": "2017-10-24T09:00:00Z", "content": "Types are going away" } GET twitter/_search { "query": { "bool": { "must": { "match": { "user_name": "kimchy" } }, "filter": { "match": { "type": "tweet" } } } } }
type
字段替代了隐式_type
字段。之前,父—子关系表示为将一个映射类型表示为父,将一个或多个其余映射类型表示为子,没有类型,咱们就不能再使用这种语法,除了表示文档之间关系的方式已更改成使用新的join
字段外,父—子特性将继续像之前同样工做。
对于用户来讲,这是一个巨大的变化,因此已经尝试让它尽量地不那么痛苦,更改将按以下方式进行:
Elasticsearch 5.6.0
index.mapping.single_type: true
将启用在6.0中强制执行的单类型/索引行为。join
字段替换。Elasticsearch 6.x
_doc
,所以索引API具备与7.0中相同的路径:PUT {index}/_doc/{id} and POST {index}/_doc
。_type
名称不能再与_id
组合以造成_uid
字段,_uid
字段已成为_id
字段的别名。join
字段。_default_
映射类型已弃用。include_type_name
),该参数指示请求和响应是否应该包含类型名称。它默认为true
,应该设置为一个显式值,以便准备升级到7.0,未设置include_type_name
将致使一个弃用警告,没有显式类型的索引将使用虚拟类型名称_doc
。Elasticsearch 7.x
type
,对于显式id,新的索引API是PUT {index}/_doc/{id}
,对于自动生成的id则是POST {index}/_doc
,注意,在7.0中,_doc
是路径的一个永久部分,它表示端点名称,而不是文档类型。include_type_name
参数默认为false
,彻底设置该参数将致使一个弃用警告。_default_
映射类型。Elasticsearch 8.x
include_type_name
参数。Reindex API可用于将多类型索引转换为单类型索引,下面的例子能够在Elasticsearch 5.6或Elasticsearch 6.x中使用,在6.x,不须要指定index.mapping.single_type
做为默认值。
第一个示例将twitter
索引拆分为tweets
索引和users
索引:
PUT users { "settings": { "index.mapping.single_type": true }, "mappings": { "_doc": { "properties": { "name": { "type": "text" }, "user_name": { "type": "keyword" }, "email": { "type": "keyword" } } } } } PUT tweets { "settings": { "index.mapping.single_type": true }, "mappings": { "_doc": { "properties": { "content": { "type": "text" }, "user_name": { "type": "keyword" }, "tweeted_at": { "type": "date" } } } } } POST _reindex { "source": { "index": "twitter", "type": "user" }, "dest": { "index": "users" } } POST _reindex { "source": { "index": "twitter", "type": "tweet" }, "dest": { "index": "tweets" } }
下一个示例添加一个自定义类型字段,并将其设置为原始_type
的值,它还将类型添加到_id
中,以防有任何不一样类型的文档具备冲突的id
:
PUT new_twitter { "mappings": { "_doc": { "properties": { "type": { "type": "keyword" }, "name": { "type": "text" }, "user_name": { "type": "keyword" }, "email": { "type": "keyword" }, "content": { "type": "text" }, "tweeted_at": { "type": "date" } } } } } POST _reindex { "source": { "index": "twitter" }, "dest": { "index": "new_twitter" }, "script": { "source": """ ctx._source.type = ctx._type; ctx._id = ctx._type + '-' + ctx._id; ctx._type = '_doc'; """ } }
在Elasticsearch 7.0中,每一个API都支持无类型请求,指定类型将产生一个弃用警告。
即便目标索引包含自定义类型,无类型API也能够工做,例如,若是索引具备自定义类型名称my_type
,则可使用无类型index
调用向其添加文档,并使用无类型get
调用加载文档。
索引建立、索引模板和映射API支持一个新的include_type_name
URL参数,该参数指定请求和响应中的映射定义是否应该包含类型名称,版本6.8中的参数默认为true
,以匹配在映射中使用类型名称的7.0以前的行为,它在7.0版本中默认为false
,将在8.0版本中删除。
它应该在6.8中明确设置,以便准备升级到7.0,为了不6.8中的弃用警告,能够将参数设置为true
或false
,在7.0中,设置include_type_name
将致使一个弃用警告。
查看一些与Elasticsearch交互的例子,这个选项设置为false
:
PUT index?include_type_name=false { "mappings": { "properties": { "foo": { "type": "keyword" } } } }
mappings
键下,没有类型名称。PUT index/_mappings?include_type_name=false { "properties": { "bar": { "type": "text" } } }
mappings
键下,没有类型名称。GET index/_mappings?include_type_name=false
上面的调用返回:
{ "index": { "mappings": { "properties": { "foo": { "type": "keyword" }, "bar": { "type": "text" } } } } }
mappings
键下,没有类型名称。在7.0中,必须使用{index}/_doc
路径调用索引API,以便自动生成_id
,使用显式id
调用{index}/_doc/{id}
。
PUT index/_doc/1 { "foo": "baz" }
{ "_index": "index", "_id": "1", "_type": "_doc", "_version": 1, "result": "created", "_shards": { "total": 2, "successful": 1, "failed": 0 }, "_seq_no": 0, "_primary_term": 1 }
相似地,get
和delete
API使用路径{index}/_doc/{id}
:
GET index/_doc/1
在7.0中,_doc
表示端点名称,而不是文档类型,_doc
组件是文档index
、get
和delete
API路径的永久部分,在8.0中不会被删除。
对于同时包含类型和端点名(如_update
)的API路径,在7.0中端点将当即跟随索引名:
POST index/_update/1 { "doc" : { "foo" : "qux" } } GET /index/_source/1
类型也不该该再出如今请求体中,下面的bulk
索引示例省略了URL和单个批量命令中的类型:
POST _bulk { "index" : { "_index" : "index", "_id" : "3" } } { "foo" : "baz" } { "index" : { "_index" : "index", "_id" : "4" } } { "foo" : "qux" }
在调用诸如_search
、_msearch
或_explain
之类的搜索API时,URL中不该该包含类型,此外,_type
字段不该该用于查询、聚合或脚本。
文档和搜索API将继续在响应中返回_type
键,以免中断响应解析,然而,键被认为是不同意的,不该该再被引用,类型将在8.0中从响应中彻底删除。
注意,当使用废弃的类型化API时,索引的映射类型将做为正常返回,可是无类型API将在响应中返回虚拟类型_doc
,例如,下面的无类型get
调用老是返回_doc
做为类型,即便映射有一个像my_type
这样的自定义类型名:
PUT index/my_type/1 { "foo": "baz" } GET index/_doc/1
{ "_index" : "index", "_type" : "_doc", "_id" : "1", "_version" : 1, "_seq_no" : 0, "_primary_term" : 1, "found": true, "_source" : { "foo" : "baz" } }
建议经过将include_type_name
设置为false
来从新添加索引模板,使其无类型,在底层,无类型模板在建立索引时将使用虚拟类型_doc
。
若是将无类型模板用于类型化索引建立调用,或者将类型化模板用于无类型索引建立调用,则仍将应用模板,但索引建立调用将决定是否应该有类型。例如在下面的示例中,index-1-01
将具备一个类型,尽管它匹配一个没有类型的模板,而index-2-01
将具备无类型,尽管它匹配一个定义了类型的模板,index-1-01
和index-2-01
都将从匹配的模板中继承foo
字段。
PUT _template/template1 { "index_patterns":[ "index-1-*" ], "mappings": { "properties": { "foo": { "type": "keyword" } } } } PUT _template/template2?include_type_name=true { "index_patterns":[ "index-2-*" ], "mappings": { "type": { "properties": { "foo": { "type": "keyword" } } } } } PUT index-1-01?include_type_name=true { "mappings": { "type": { "properties": { "bar": { "type": "long" } } } } } PUT index-2-01 { "mappings": { "properties": { "bar": { "type": "long" } } } }
在隐式索引建立的状况下,由于文档在索引中被索引,而索引还不存在,因此老是使用模板,这一般不是一个问题,由于无类型索引调用要处理有类型的索引。
在由6.8和7.0节点组成的集群中,应该在索引建立之类的索引API中指定参数include_type_name
,这是由于参数在6.8和7.0之间有不一样的默认值,因此相同的映射定义对两个节点版本都无效。
诸如bulk
和update
之类的无类型文档API仅在7.0版本时可用,不能用于6.8节点,对于执行文档查找的查询的无类型版本,如terms
,也是如此。