Elasticsearch 映射类型的变迁史

2024-02-23 20:48

本文主要是介绍Elasticsearch 映射类型的变迁史,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

  原文为官方文档,此篇文章为翻译,不能保证完全正确性,有地方存在歧义或者不准确,仅做参考,建议阅读官方原文:https://www.elastic.co/guide/en/elasticsearch/reference/current/removal-of-types.html

一、重要需知

  在Elasticsearch 7.0.0 或更高版本中创建的索引不再接受_default_映射。在6.x中创建的索引将继续在6.x中运行。在7.0的API中,类型已弃用,并且对索引创建、put映射、get映射、put模板、get模板和get字段映射的API进行了重大更改。

二、什么是映射类型(mapping types)?

  从Elasticsearch的第一个版本开始,每个文档都存储在一个索引中并分配了一个映射类型。映射类型用于表示要建立索引的文档或者实体的类型,例如twitter索引可能具有user(用户)类型和tweet(推文)类型。
  每种映射类型都可以有自己的字段,因此user类型可以有full_name字段、user_name字段和email字段,而tweet类型可以有content字段、tweeted_at(发布推文的时间)字段、以及和user类型类似的user_name字段。
  每个文档都有一个包含类型名称的_type元数据字段,我们可以在搜索中指定类型名称,将搜索限制在一种或多种类型。

GET twitter/user,tweet/_search
{"query": {"match": {"user_name": "kimchy"}}
}

  _type字段与文档的_id组合在一起可以生成_uid字段,因此具有相同_id的不同类型的文档可以存在于单个索引中。映射类型还用于在文档之间建立父子关系,因此question类型的文档可以是answer类型文档的父级。

三、为什么要删除映射类型?

  最初,我们谈到的“index”类似于SQL数据库中的“database”,“type”等同于“table”。这是一个不合适的类比,会导致错误的设想。在SQL数据库中,表彼此独立,一个表中的列与另一表中具有相同名称的列毫无关系,但是映射类型的字段却不是这种情况。
  在一个Elasticsearch索引中,所有不同类型的同名字段内部是由相同的Lucene字段支持。换句话说,在上面的例子中,user类型中的user_name字段和tweet类型中的user_name字段是储存在完全相同的字段中,并且两个user_name字段在这两种类型中必须具有相同的映射(定义)。例如,当您希望删除同一索引中的一种类型同名的日期字段和另一种类型同名的布尔字段时,这可能会导致问题。
  最重要的是,存储在同一索引中具有很少或没有共同字段的不同实体会导致数据稀疏,并干扰Lucene有效压缩文档的能力。
  由于这些原因,我们决定从Elasticsearch中删除映射类型的概念。

四、映射类型的替代方法

1、为每个文档类型创建一个索引

  第一个选择就是为每个文档类型创建一个索引,来代替将user和tweet都存储在twitter索引中。您可以将推文存储在tweet索引中,将用户存储在user索引中。索引之间彼此完全独立,因此索引之间的字段类型不会发生冲突。
  这种方法有两个好处:
   • 数据可能更密集,因此可以从Lucene中使用的压缩技术中受益。
   • 在全文搜索中用于评分的术语统计可能更准确了,因为同一索引中的所有文档都代表一个实体。
  每个索引的大小可以根据包含的文档数量进行适当调整,您可以为user设置使用较少数量的主分片,为tweet设置使用较大数量的主分片。

2、自定义类型字段

  当然,一个集群中可以存在多少个主要分片是有限制的,因此您可能不想只存储几千个文档就浪费了整个分片。在这种情况下,您可以实现自己的自定义类型字段,它的工作方式与旧_type相似。让我们以上面的用户/推文示例为例。
  最初,可能会这样做(6.x以下可以这么做,因为6.x每个索引只允许一个单一类型):

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"}}
}

  您可以通过添加自定义类型字段来实现相同的目的,如下所示(7.x版本以下可以这么做):

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" }}}}
}

五、文档父子关系的建立将无映射类型

  以前,通过将一种映射类型作为父级,而将另一种或多种其他映射类型作为子级来表示父子关系。没有类型,我们将无法再使用此语法。父子功能将继续像以前一样起作用,除了表达文档之间关系的方式已更改为使用新的join字段来实现。

六、删除映射类型时间表

  对于用户来说,移除映射类型这是一个很大的变化,因此我们试图使其尽可能轻松,更改将按以下方式一步步推出:

Elasticsearch 5.6.0• 在索引上设置index.mapping.single_type: true启用单一索引类型行为,该行为将在6.0中强制执行。• 在5.6中创建的父子关系上可以使用join字段替换。Elasticsearch 6.x• 在5.x中创建的索引将像在5.x中一样继续在6.x中运行。• 在6.x中创建的索引仅允许每个索引使用一种类型,该类型可以使用任何名称,但是只能有一个。首选的类型名称是_doc,因此索引API具有与7.0中相同的路径:PUT {index}/_ doc/{id} 和 POST {index}/_doc。• _type名称不能再与_id组合以形成_uid字段。_uid字段已成为_id字段的别名。   • 新索引不再支持以前文档间建立父/子关系的旧方法,而应使用join字段实现。   •  _default_ 映射类型已弃用。• 在6.8中,创建索引、索引模板和映射(mappings)的API支持查询字符串参数include_type_name,该参数表示请求和响应是否应包括类型名称,默认为true。Elasticsearch 7.x• 在请求中指定类型已经被弃用。不再为文档创建索引就必须需要一种文档类型。对于显式ID,新索引API为PUT {index}/_doc/{id};对于自动生成的ID,则为POST {index}/_doc。请注意,在7.0版本中,doc是路径的永久部分,它表示端点名称而不是文档类型了。• 索引创建、索引模板和映射(mappings)的API中的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,因为它是默认值。

1、为每个文档类型创建一个索引

  依照最开始的示例,我们将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","type": "_doc"}
}POST _reindex
{"source": {"index": "twitter","type": "tweet"},"dest": {"index": "tweets","type": "_doc"}
}

2、自定义类型字段

  以下示例将添加了一个自定义类型字段,并将其设置为原始_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';"""}
}

八、7.0中的无类型API的使用

  在Elasticsearch 7.0中,每个API将支持无类型的请求,如果指定了类型将产生弃用警告。但是需要注意的是,即使目标索引包含了自定义类型,无类型的API也能正常工作。例如,如果索引的自定义类型名为my_type,我们可以使用无类型索引调用向其中添加文档,也可以使用无类型get调用加载文档。如下:

PUT test/my_type/1
{"name" : "test"
}
GET test/my_type/1
GET test/_doc/1

  结果:GET获取文档数据,两者结果一样,但是前者包含了类型名称,所以会有弃用警告,后者没有。

# GET test/my_type/1
#! Deprecation: [types removal] Specifying types in document get requests is deprecated, use the /{index}/_doc/{id} endpoint instead.
{"_index" : "test","_type" : "my_type","_id" : "1","_version" : 2,"_seq_no" : 1,"_primary_term" : 1,"found" : true,"_source" : {"name" : "test"}
}# GET test/_doc/1
{"_index" : "test","_type" : "_doc","_id" : "1","_version" : 2,"_seq_no" : 1,"_primary_term" : 1,"found" : true,"_source" : {"name" : "test"}
}

1、Index APIs

  索引创建、索引模板和映射的API支持在URL中使用include_type_name参数,该参数指定请求和响应中的映射定义是否应包含类型名称,可以设置为true或false。在6.8版中,该参数默认为true,以支持在7.0之前在映射(mappings)中使用类型名称的行为。在7.0版中默认为false,在版本8.0中将被删除。
  将此选项设置为false,如下与Elasticsearch进行交互的一些示例(以下映射直接包含在映射键下,没有类型名称)。

PUT /my-index-000001?include_type_name=false
{"mappings": {"properties": { "foo": {"type": "keyword"}}}
}PUT /my-index-000001/_mappings?include_type_name=false
{"properties": { "bar": {"type": "text"}}
}GET /my-index-000001/_mappings?include_type_name=false

结果:

{"my-index-000001" : {"mappings" : {"properties" : {"bar" : {"type" : "text"},"foo" : {"type" : "keyword"}}}}
}

2、Document APIs

  在7.0中,索引API必须使用{index}/_doc路径进行调用。对于显式ID,索引API为PUT {index}/_doc/{id};对于自动生成的ID,则为POST {index}/_doc。

PUT /my-index-000001/_doc/1
{"foo": "baz"
}

结果:

{"_index" : "my-index-000001","_type" : "_doc","_id" : "1","_version" : 1,"result" : "created","_shards" : {"total" : 2,"successful" : 1,"failed" : 0},"_seq_no" : 0,"_primary_term" : 1
}

同样,获取和删除APl使用路径也要为{index}/_ doc/{id}:

GET /my-index-000001/_doc/1

  需要注意的是,在7.0中,_doc表示端点名称,而不是文档类型。 _doc组件是文档索引、获取和删除API路径的永久部分,在8.0中不会删除。
  对于像_update这种同时包含类型和端点名称的API路径,在7.0中,_update直接跟在索引名称后面即可:

POST /my-index-000001/_update/1
{"doc" : {"foo" : "qux"}
}GET /my-index-000001/_source/1

  类型也不应再出现在请求正文中,类型也不应再出现在请求正文中。以下创建批量索引示例在URL和单个批量命令中都省略了该类型:

POST _bulk
{ "index" : { "_index" : "my-index-000001", "_id" : "3" } }
{ "foo" : "baz" }
{ "index" : { "_index" : "my-index-000001", "_id" : "4" } }
{ "foo" : "qux" }

3、Search APIs

  调用诸如_search,_msearch或_explain之类的搜索API时,URL中不应包含类型。此外,不应在查询、聚合或脚本中使用类型字段。

4、Types in responses

  文档和搜索API将继续在回应中返回_type 键,以避免中断响应解析。但是该键被认为已弃用,不应再被引用。在8.0版中,类型将从回应中完全删除。
  请注意,当使用不推荐使用的类型API时,索引的映射类型将正常返回,但是无类型API会在响应中返回伪类型_doc。例如,即使映射具有自定义类型名称(例如my_type),以下无类型的get调用也将始终以doc作为类型返回:

PUT /my-index-000001/my_type/1
{"foo": "baz"
}GET /my-index-000001/_doc/1

结果:

{"_index" : "my-index-000001","_type" : "_doc","_id" : "1","_version" : 1,"_seq_no" : 0,"_primary_term" : 1,"found": true,"_source" : {"foo" : "baz"}
}

5、Index templates

  建议通过将include_type_name设置为false来重新添加索引模板,使索引模板无类型。在后台,无类型的模板在创建索引时将使用伪类型_doc。
  如果将无类型的模板与有类型的索引创建调用一起使用,或者将有类型的模板与无类型的索引创建调用一起使用,则仍将应用该模板,但是是否应该有一个类型将由索引的创建调用决定。
  例如,在下面的示例中,尽管index-1-01与无类型的模板匹配,但index-1-01将具有类型;尽管index-2-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、混合版本集群

  在由6.8和7.0节点组成的集群中,应在诸如索引创建之类的索引API中指定参数include_type_name。这是因为参数在6.8和7.0之间具有不同的默认值,因此相同的映射定义对两个节点版本均无效。
  无类型文档API(例如批量和更新)仅在7.0以后可用,不适用于6.8节点。对于执行文档查找的无类型查询,例如术语,也是如此。

这篇关于Elasticsearch 映射类型的变迁史的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/739881

相关文章

Mysql 中的多表连接和连接类型详解

《Mysql中的多表连接和连接类型详解》这篇文章详细介绍了MySQL中的多表连接及其各种类型,包括内连接、左连接、右连接、全外连接、自连接和交叉连接,通过这些连接方式,可以将分散在不同表中的相关数据... 目录什么是多表连接?1. 内连接(INNER JOIN)2. 左连接(LEFT JOIN 或 LEFT

Redis的Hash类型及相关命令小结

《Redis的Hash类型及相关命令小结》edisHash是一种数据结构,用于存储字段和值的映射关系,本文就来介绍一下Redis的Hash类型及相关命令小结,具有一定的参考价值,感兴趣的可以了解一下... 目录HSETHGETHEXISTSHDELHKEYSHVALSHGETALLHMGETHLENHSET

Python中异常类型ValueError使用方法与场景

《Python中异常类型ValueError使用方法与场景》:本文主要介绍Python中的ValueError异常类型,它在处理不合适的值时抛出,并提供如何有效使用ValueError的建议,文中... 目录前言什么是 ValueError?什么时候会用到 ValueError?场景 1: 转换数据类型场景

C# dynamic类型使用详解

《C#dynamic类型使用详解》C#中的dynamic类型允许在运行时确定对象的类型和成员,跳过编译时类型检查,适用于处理未知类型的对象或与动态语言互操作,dynamic支持动态成员解析、添加和删... 目录简介dynamic 的定义dynamic 的使用动态类型赋值访问成员动态方法调用dynamic 的

基于MySQL Binlog的Elasticsearch数据同步实践

一、为什么要做 随着马蜂窝的逐渐发展,我们的业务数据越来越多,单纯使用 MySQL 已经不能满足我们的数据查询需求,例如对于商品、订单等数据的多维度检索。 使用 Elasticsearch 存储业务数据可以很好的解决我们业务中的搜索需求。而数据进行异构存储后,随之而来的就是数据同步的问题。 二、现有方法及问题 对于数据同步,我们目前的解决方案是建立数据中间表。把需要检索的业务数据,统一放到一张M

零基础学习Redis(10) -- zset类型命令使用

zset是有序集合,内部除了存储元素外,还会存储一个score,存储在zset中的元素会按照score的大小升序排列,不同元素的score可以重复,score相同的元素会按照元素的字典序排列。 1. zset常用命令 1.1 zadd  zadd key [NX | XX] [GT | LT]   [CH] [INCR] score member [score member ...]

自定义类型:结构体(续)

目录 一. 结构体的内存对齐 1.1 为什么存在内存对齐? 1.2 修改默认对齐数 二. 结构体传参 三. 结构体实现位段 一. 结构体的内存对齐 在前面的文章里我们已经讲过一部分的内存对齐的知识,并举出了两个例子,我们再举出两个例子继续说明: struct S3{double a;int b;char c;};int mian(){printf("%zd\n",s

【编程底层思考】垃圾收集机制,GC算法,垃圾收集器类型概述

Java的垃圾收集(Garbage Collection,GC)机制是Java语言的一大特色,它负责自动管理内存的回收,释放不再使用的对象所占用的内存。以下是对Java垃圾收集机制的详细介绍: 一、垃圾收集机制概述: 对象存活判断:垃圾收集器定期检查堆内存中的对象,判断哪些对象是“垃圾”,即不再被任何引用链直接或间接引用的对象。内存回收:将判断为垃圾的对象占用的内存进行回收,以便重新使用。

flume系列之:查看flume系统日志、查看统计flume日志类型、查看flume日志

遍历指定目录下多个文件查找指定内容 服务器系统日志会记录flume相关日志 cat /var/log/messages |grep -i oom 查找系统日志中关于flume的指定日志 import osdef search_string_in_files(directory, search_string):count = 0

两个月冲刺软考——访问位与修改位的题型(淘汰哪一页);内聚的类型;关于码制的知识点;地址映射的相关内容

1.访问位与修改位的题型(淘汰哪一页) 访问位:为1时表示在内存期间被访问过,为0时表示未被访问;修改位:为1时表示该页面自从被装入内存后被修改过,为0时表示未修改过。 置换页面时,最先置换访问位和修改位为00的,其次是01(没被访问但被修改过)的,之后是10(被访问了但没被修改过),最后是11。 2.内聚的类型 功能内聚:完成一个单一功能,各个部分协同工作,缺一不可。 顺序内聚: