返回顶部
首页 > 资讯 > 数据库 >一文搞懂 Elasticsearch 之 Mapping
  • 388
分享到

一文搞懂 Elasticsearch 之 Mapping

一文搞懂ElasticsearchMapping 2018-08-02 00:08:09 388人浏览 猪猪侠
摘要

作为 elasticsearch 的“表结构定义”的 Mapping,你可能需要了解下! 这篇文章主要介绍 Mapping、Dynamic Mapping 以及 ElasticSearch 是如何自动判

一文搞懂 Elasticsearch 之 Mapping

作为 elasticsearch 的“表结构定义”的 Mapping,你可能需要了解下!

这篇文章主要介绍 Mapping、Dynamic Mapping 以及 ElasticSearch 是如何自动判断字段的类型,同时介绍 Mapping 的相关参数设置。

首先来看下什么是 Mapping:

什么是 Mapping?

在一篇文章带你搞定 ElasticSearch 术语中,我们讲到了 Mapping 类似于数据库中的表结构定义 schema,它有以下几个作用:

  • 定义索引中的字段的名称
  • 定义字段的数据类型,比如字符串、数字、布尔
  • 字段,倒排索引的相关配置,比如设置某个字段为不被索引、记录 position 等

在 ES 早期版本,一个索引下是可以有多个 Type 的,从 7.0 开始,一个索引只有一个 Type,也可以说一个 Type 有一个 Mapping 定义。

在了解了什么是 Mapping 之后,接下来对 Mapping 的设置做下介绍:

Mapping 设置

PUT users
{
    "mappings": {
        "_doc": {
            "dynamic": false
        }
    }
}

在创建一个索引的时候,可以对 dynamic 进行设置,可以设成 falsetrue 或者 strict

Dynamic Mappings 设置

比如一个新的文档,这个文档包含一个字段,当 Dynamic 设置为 true 时,这个文档可以被索引进 ES,这个字段也可以被索引,也就是这个字段可以被搜索,Mapping 也同时被更新;当 dynamic 被设置为 false 时候,存在新增字段的数据写入,该数据可以被索引,但是新增字段被丢弃;当设置成 strict 模式时候,数据写入直接出错。

另外还有 index 参数,用来控制当前字段是否被索引,默认为 true,如果设为 false,则该字段不可被搜索。

参数 index_options 用于控制倒排索引记录的内容,有如下 4 种配置:

  • doc:只记录 doc id
  • freqs:记录 doc idterm frequencies
  • positions:记录 doc idterm frequenciesterm position
  • offsets:记录 doc idterm frequenciesterm positioncharacter offects

另外,text 类型默认配置为 positions,其他类型默认为 doc,记录内容越多,占用存储空间越大。

null_value 主要是当字段遇到 null 值时的处理策略,默认为 NULL,即空值,此时 ES 会默认忽略该值,可以通过设定该值设定字段的默认值,另外只有 KeyWord 类型支持设定 null_value

copy_to 作用是将该字段的值复制到目标字段,实现类似 _all 的作用,它不会出现在 _source 中,只用来搜索。

除了上述介绍的参数,还有许多参数,大家感兴趣的可以在官方文档中进行查看。

学习了 Mapping 的设置之后,让我们来看下字段的数据类型有哪些吧!

字段数据类型

ES 字段类型类似于 Mysql 中的字段类型,ES 字段类型主要有:核心类型、复杂类型、地理类型以及特殊类型,具体的数据类型如下图所示:

字段数据类型

核心类型

从图中可以看出核心类型可以划分为字符串类型、数字类型、日期类型、布尔类型、基于 BASE64 的二进制类型、范围类型。

字符串类型

其中,在 ES 7.x 有两种字符串类型:textkeyword,在 ES 5.x 之后 string 类型已经不再支持了。

text 类型适用于需要被全文检索的字段,例如新闻正文、邮件内容等比较长的文字,text 类型会被 Lucene 分词器(Analyzer)处理为一个个词项,并使用 Lucene 倒排索引存储,text 字段不能被用于排序,如果需要使用该类型的字段只需要在定义映射时指定 JSON 中对应字段的 typetext

keyword 适合简短、结构化字符串,例如主机名、姓名、商品名称等,可以用于过滤、排序、聚合检索,也可以用于精确查询

数字类型

数字类型分为 long、integer、short、byte、double、float、half_float、scaled_float

数字类型的字段在满足需求的前提下应当尽量选择范围较小的数据类型,字段长度越短,搜索效率越高,对于浮点数,可以优先考虑使用 scaled_float 类型,该类型可以通过缩放因子来精确浮点数,例如 12.34 可以转换为 1234 来存储。

日期类型

在 ES 中日期可以为以下形式:

  • 格式化的日期字符串,例如 2020-03-17 00:00、2020/03/17
  • 时间戳(和 1970-01-01 00:00:00 UTC 的差值),单位毫秒或者秒

即使是格式化的日期字符串,ES 底层依然采用的是时间戳的形式存储。

布尔类型

jsON 文档中同样存在布尔类型,不过 JSON 字符串类型也可以被 ES 转换为布尔类型存储,前提是字符串的取值为 true 或者 false,布尔类型常用于检索中的过滤条件。

二进制类型

二进制类型 binary 接受 BASE64 编码的字符串,默认 store 属性为 false,并且不可以被搜索。

范围类型

范围类型可以用来表达一个数据的区间,可以分为5种:integer_range、float_range、long_range、double_range 以及 date_range

复杂类型

复合类型主要有对象类型(object)和嵌套类型(nested):

对象类型

JSON 字符串允许嵌套对象,一个文档可以嵌套多个、多层对象。可以通过对象类型来存储二级文档,不过由于 Lucene 并没有内部对象的概念,ES 会将原 JSON 文档扁平化,例如文档:

{
    "name": {
        "first": "wu",
        "last": "px"
    }
}

实际上 ES 会将其转换为以下格式,并通过 Lucene 存储,即使 nameobject 类型:

{
    "name.first": "wu",
    "name.last": "px"
}

嵌套类型

嵌套类型可以看成是一个特殊的对象类型,可以让对象数组独立检索,例如文档:

{
  "group": "users",
  "username": [
    { "first": "wu", "last": "px"},
    { "first": "hu", "last": "xy"},
    { "first": "wu", "last": "mx"}
  ]
}

username 字段是一个 JSON 数组,并且每个数组对象都是一个 JSON 对象。如果将 username 设置为对象类型,那么 ES 会将其转换为:

{
  "group": "users",
  "username.first": ["wu", "hu", "wu"],
  "username.last": ["px", "xy", "mx"]
}

可以看出转换后的 JSON 文档中 firstlast 的关联丢失了,如果尝试搜索 firstwulastxy 的文档,那么成功会检索出上述文档,但是 wuxy 在原 JSON 文档中并不属于同一个 JSON 对象,应当是不匹配的,即检索不出任何结果。

嵌套类型就是为了解决这种问题的,嵌套类型将数组中的每个 JSON 对象作为独立的隐藏文档来存储,每个嵌套的对象都能够独立地被搜索,所以上述案例中虽然表面上只有 1 个文档,但实际上是存储了 4 个文档。

地理类型

地理类型字段分为两种:经纬度类型和地理区域类型:

经纬度类型

经纬度类型字段(geo_point)可以存储经纬度相关信息,通过地理类型的字段,可以用来实现诸如查找在指定地理区域内相关的文档、根据距离排序、根据地理位置修改评分规则等需求。

地理区域类型

经纬度类型可以表达一个点,而 geo_shape 类型可以表达一块地理区域,区域的形状可以是任意多边形,也可以是点、线、面、多点、多线、多面等几何类型。

特殊类型

特殊类型包括 IP 类型、过滤器类型、Join 类型、别名类型等,在这里简单介绍下 IP 类型和 Join 类型,其他特殊类型可以查看官方文档。

IP 类型

IP 类型的字段可以用来存储 IPv4 或者 IPv6 地址,如果需要存储 IP 类型的字段,需要手动定义映射:

{
  "mappings": {
    "properties": {
      "my_ip": {
        "type": "ip"
      }
    }
  }
}

Join 类型

Join 类型是 ES 6.x 引入的类型,以取代淘汰的 _parent 元字段,用来实现文档的一对一、一对多的关系,主要用来做父子查询。

Join 类型的 Mapping 如下:

PUT my_index
{
  "mappings": {
    "properties": {
      "my_join_field": { 
        "type": "join",
        "relations": {
          "question": "answer" 
        }
      }
    }
  }
}

其中,my_join_field 为 Join 类型字段的名称;relations 指定关系:questionanswer 的父类。

例如定义一个 ID 为 1 的父文档:

PUT my_join_index/1?refresh
{
  "text": "This is a question",
  "my_join_field": "question" 
}

接下来定义一个子文档,该文档指定了父文档 ID 为 1:

PUT my_join_index/_doc/2?routing=1&refresh 
{
  "text": "This is an answer",
  "my_join_field": {
    "name": "answer", 
    "parent": "1" 
  }
}

再了解完字段数据类型后,再让我们看下什么是 Dynamic Mapping?

什么是 Dynamic Mapping?

Dynamic Mapping 机制使我们不需要手动定义 Mapping,ES 会自动根据文档信息来判断字段合适的类型,但是有时候也会推算的不对,比如地理位置信息有可能会判断为 Text,当类型如果设置不对时,会导致一些功能无法正常工作,比如 Range 查询。

类型自动识别

ES 类型的自动识别是基于 JSON 的格式,如果输入的是 JSON 是字符串且格式为日期格式,ES 会自动设置成 Date 类型;当输入的字符串是数字的时候,ES 默认会当成字符串来处理,可以通过设置来转换成合适的类型;如果输入的是 Text 字段的时候,ES 会自动增加 keyword 子字段,还有一些自动识别如下图所示:

类型自动识别

下面我们通过一个例子是看看是怎么类型自动识别的,输入如下请求,创建索引:

PUT /mapping_test/_doc/1
{
  "uid": "123",
  "username": "wupx",
  "birth": "2020-03-16",
  "married": false,
  "age": 18,
  "heigh": 180,
  "tags": [
    "java",
    "boy"
  ],
  "money": 999.9
}

然后使用 GET /mapping_test/_mapping 查看,结果如下图所示:

可以从结果中看出,ES 会根据文档信息自动推算出合适的类型。

哦豁,万一我想修改 Mapping 的字段类型,能否更改呢?让我们分以下两种情况来探究下:

修改 Mapping 字段类型?

如果是新增加的字段,根据 Dynamic 的设置分为以下三种状况:

  • 当 Dynamic 设置为 true 时,一旦有新增字段的文档写入,Mapping 也同时被更新。
  • 当 Dynamic 设置为 false 时,索引的 Mapping 是不会被更新的,新增字段的数据无法被索引,也就是无法被搜索,但是信息会出现在 _source 中。
  • 当 Dynamic 设置为 strict 时,文档写入会失败。

另外一种是字段已经存在,这种情况下,ES 是不允许修改字段的类型的,因为 ES 是根据 Lucene 实现的倒排索引,一旦生成后就不允许修改,如果希望改变字段类型,必须使用 Reindex api 重建索引。

不能修改的原因是如果修改了字段的数据类型,会导致已被索引的无法被搜索,但是如果是增加新的字段,就不会有这样的影响。

总结

本文主要介绍了 Mapping 和 Dynamic Mapping,同时对字段类型做了详细介绍,也介绍了在 ES 中是如何对字段类型做推算的,了解了 Mapping 的相关参数设置。

在公众号【武培轩】回复【es】获取思维导图以及源代码。

参考文献

《Elasticsearch技术解析与实战》

Elastic Stack从入门到实践

Elasticsearch核心技术与实战

https://www.elastic.co/guide/en/elasticsearch/reference/7.1/mapping.html

您可能感兴趣的文档:

--结束END--

本文标题: 一文搞懂 Elasticsearch 之 Mapping

本文链接: https://lsjlt.com/news/5042.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • 一文搞懂 Elasticsearch 之 Mapping
    作为 Elasticsearch 的“表结构定义”的 Mapping,你可能需要了解下! 这篇文章主要介绍 Mapping、Dynamic Mapping 以及 ElasticSearch 是如何自动判...
    99+
    2018-08-02
    一文搞懂 Elasticsearch Mapping
  • 一文搞懂HBA卡
    HBA卡是一个简称,准确叫法应该是:主机总线适配器(Host Bus Adapter,HBA),也叫做FC-HBA卡(俗称:光纤网卡)、iSCSI-HBA卡(RJ45接口)。这是一个在服务器和存储装置间提供输入/输出(I/O)处理和物理连接...
    99+
    2023-08-31
    服务器
  • netstat命令,一文搞懂
    netstat命令是一个网络工具,用于显示计算机网络的连接状态和统计数据。它可以列出所有活动的网络连接,包括正在监听的端口、正在建立...
    99+
    2023-09-12
    netstat
  • 一文搞懂MySQL预编译
    1、预编译的好处   大家平时都使用过JDBC中的PreparedStatement接口,它有预编译功能。什么是预编译功能呢?它有什么好处呢?   当客户发送一条SQL语句给服务器后,服务器总是需要校验SQL语句的语...
    99+
    2022-05-23
    MySQL 预编译 MySQL 编译
  • 一文搞懂Spring中的JavaConfig
    目录配置类注册组件扫描包配置事务注解驱动单元测试加载配置类properties配置文件加载(了解)aspectj注解开关传统spring一般都是基于xml配置的,不过后来新增了许多J...
    99+
    2024-04-02
  • 一文搞懂JSON(JavaScript Object Notation)
    目录JSON出现Json结构Json对象Json对象与JavaScript对象JSON 和 JavaScript 对象互转Json数组复杂数组类型复杂对象数组组合对象包含数组数组包含...
    99+
    2024-04-02
  • 一文搞懂Java顶层类之Object类的使用
    目录概述toString方法方法摘要覆盖重写equals方法方法摘要默认地址比较对象内容比较Objects类概述 java.lang.Object类是Java语言中的根类,即所有类的...
    99+
    2022-11-16
    Java Object类使用 Java Object类
  • 一文搞懂Python Sklearn库使用
    目录1、LabelEncoder2、OneHotEncoder3、sklearn.model_selection.train_test_split随机划分训练集和测试集4、pipeline5 perdict...
    99+
    2022-06-03
    Python Sklearn库 Python Sklearn库使用
  • 一文搞懂MySQL事务特性
    本文主要给大家简单讲讲MySQL事务特性,相关专业术语大家可以上网查查或者找一些相关书籍补充一下,这里就不涉猎了,我们就直奔主题吧,希望MySQL事务特性这篇文章可以给大家带来一些实际帮助。事务特性ACID...
    99+
    2024-04-02
  • 一文搞懂Codec2框架解析
    目录1 前言–Codec2.0是什么2 Codec2.0框架3 流程解析3.1 初始化流程3.2 启动流程3.3 Input Buffer的回调3.4 Output Buffer的回...
    99+
    2024-04-02
  • 一文搞懂Codec2解码组件
    目录1 前言2 组件的创建3 组件接口4 组件运行原理5 小结1 前言 在本篇中,我们将关注Codec 2.0以下几个问题: 1.从顶而下,一个解码组件是如何创建的 2.组件的接口有...
    99+
    2024-04-02
  • 一文搞懂UART通信协议
    目录 1、UART简介 2、UART特性 3、UART协议帧 3.1、起始位 3.2、数据位 3.3、奇偶校验位 3.4、停止位 4、UART通信步骤 1、UART简介 UART(Universal Asynchronous Receiv...
    99+
    2023-10-12
    UART协议 嵌入式 通信协议 单片机
  • 一文带你搞懂Java8的LocalDateTime
    目录前言LocalDateTime获取当前时间获取当前时间的年月日时分秒给LocalDateTime赋值时间与字符串相互转换时间运算:加上对应时间时间运算:减去对应时间两个时间比较利...
    99+
    2023-05-14
    Java8 LocalDateTime使用 Java8 LocalDateTime
  • 一文搞懂SQL注入攻击
    目录1. 前言2. SQL注入简介(1)SQL语言(2)SQL注入3. SQL注入步骤(1)发现漏洞(2)信息收集(3)攻击Web系统(猜解用户名和密码)(4)获取管理员权限4. 防范SQL注入(1)使用参数化查询或存储...
    99+
    2023-04-19
    SQL注入攻击 SQL注入
  • 一文搞懂Java桥接方法
    目录1.桥接方法简介2. 什么时候会生成桥接方法3. 为什么生成泛型方法4. 根据桥接方法获取实际泛型方法 1.桥接方法简介 桥接方法是jdk1.5引入泛型后,为使java...
    99+
    2024-04-02
  • 一文带你彻底搞懂Vuex
    大家可以思考一下,组件之间的传值有哪些?有父子通讯,兄弟组件通讯......但是传参对于多层嵌套就显得非常繁琐,代码维护也会非常麻烦。因此vuex就是把组件共享状态抽取出来以一个全局单例模式管理,把共享的数据函数放进vuex中,任何组件都可...
    99+
    2022-11-22
    Vue vue3 vue.js VueX
  • 一文搞懂Java ScheduledExecutorService的使用
    目录一、创建ScheduledExecutorService对象二、ScheduledExecutorService方法三、固定速率和固定延时的区别1. 固定速率2. 固定延时四、调...
    99+
    2022-11-13
    Java ScheduledExecutorService使用 Java ScheduledExecutorService
  • 一文搞懂MySQL执行流程
    目录 一、MySQL技术架构 二、执行流程 1.连接器 2.查询缓存 3.解析SQL 4.执行SQL 总结 一、MySQL技术架构   可以看到,MySQL的技术架构共分为两层:Server层和存储引擎层 Server 层负责建立连接、分...
    99+
    2023-10-27
    mysql 面试 后端 数据库
  • 一文搞懂JavaScript中最难理解概念之一的闭包
    目录一、闭包的概念二、怎么实现闭包三、闭包的用途1.封装私有变量2. 做缓存3. 模块化编程(实现共有变量)四、闭包的缺点五、最后的话一、闭包的概念 当通过调用外部函数返回的内部函数...
    99+
    2023-05-14
    JavaScript闭包实现 JavaScript闭包应用 JavaScript闭包
  • elasticsearch索引index之put mapping怎么设置
    本篇内容主要讲解“elasticsearch索引index之put mapping怎么设置”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“elasticsearch索引index之put...
    99+
    2023-06-30
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作