Elasticsearch——映射、类型、映射参数详解

作者简介:大家好,我是smart哥,前中兴通讯、美团架构师,现某互联网公司CTO

联系qq:184480602,加我进群,大家一起学习,一起进步,一起对抗互联网寒冬

学习必须往深处挖,挖的越深,基础越扎实!

阶段1、深入多线程

阶段2、深入多线程设计模式

阶段3、深入juc源码解析


阶段4、深入jdk其余源码解析


阶段5、深入jvm源码解析

码哥源码部分

码哥讲源码-原理源码篇【2024年最新大厂关于线程池使用的场景题】

码哥讲源码【炸雷啦!炸雷啦!黄光头他终于跑路啦!】

码哥讲源码-【jvm课程前置知识及c/c++调试环境搭建】

​​​​​​码哥讲源码-原理源码篇【揭秘join方法的唤醒本质上决定于jvm的底层析构函数】

码哥源码-原理源码篇【Doug Lea为什么要将成员变量赋值给局部变量后再操作?】

码哥讲源码【你水不是你的错,但是你胡说八道就是你不对了!】

码哥讲源码【谁再说Spring不支持多线程事务,你给我抽他!】

终结B站没人能讲清楚红黑树的历史,不服等你来踢馆!

打脸系列【020-3小时讲解MESI协议和volatile之间的关系,那些将x86下的验证结果当作最终结果的水货们请闭嘴】

1、映射

1.1、动态映射

底层会自动的根据存入的数据判断数据类型,这种自动分析就叫动态映射。

创建一个索引:

    PUT book/_doc/1
    {
      "name": "三国演义",
      "author": "罗贯中",
      "price": 20,
      "publishDate": "2020-01-01"
    }

查看动态映射:

    GET /book/_mapping

返回:

    {
      "book" : {
        "mappings" : {
          "properties" : {
            "author" : {
              "type" : "text",
              "fields" : {
                "keyword" : {
                  "type" : "keyword",
                  "ignore_above" : 256
                }
              }
            },
            "name" : {
              "type" : "text",
              "fields" : {
                "keyword" : {
                  "type" : "keyword",
                  "ignore_above" : 256
                }
              }
            },
            "price" : {
              "type" : "long"
            },
            "publishDate" : {
              "type" : "date"
            }
          }
        }
      }
    }

text:字符串,存储需要分词的。
keyword:字符串,存储不需要分词的。

动态映射还有一个日期检测的问题。可以看到 publishDate 的数据类型会被推断是日期类型。如果这个时候再存一本书,publishDate 不是日期,而是其他数据类型,那么存储一定会报错;如果是要存字符串类型,我们存数字类型,都一样可以,因为字符串跟数字可以转换,但是日期类型不能转换。

要解决这个问题,可以使用静态映射,即在索引定义时,将 publishDate 指定为 text 类型。也可以关闭日期检测:

    PUT blog 
    {
      "mappings": {
        "date_detection": false
      }
    }

默认情况下,文档中如果新增了字段,mappings 中也会自动新增进来。有的时候,如果希望新增字段时,能够抛出异常来提醒开发者,这个可以通过 mappings 中 dynamic属性来配置。但是这么设置,其实也就是变成静态映射了。

1.2、静态映射

如果希望新增字段时,能够抛出异常来提醒开发者,这个可以通过 mappings 中 dynamic属性来配置。

dynamic 属性有三种取值:

  • true:默认即此。自动添加新字段。
  • false:忽略新字段。
  • strict:严格模式,发现新字段会抛出异常。
    PUT blog 
    {
      "mappings": {
        "dynamic": "strict",
        "properties": {
          "title": {
            "type": "text"
          },
          "age": {
            "type": "long"
          }
        }
      }
    }

静态映射的意思就是在定义索引时,就把索引中的所有字段类型,统统提前定义枚举好,那么以后往索引中加数据和字段时,就只能按照规定好的加。

    PUT /user 
    {
      "mappings": {
        "properties": {
          "name": {
            "type": "text"
          },
          "phone": {
            "type": "keyword"
          },
          "age": {
            "type": "integer"
          }
        }
      }
    }

1.3、类型推断

JSON中的数据 自动推断出来的数据类型
null 没有字段被添加
true/false boolean
浮点数字 float
数字 long
JSON对象 object
数组 数组中的第一个非空值决定
string text/keyword/date/double/long都有可能

2、核心类型

2.1、字符串类型

  • string :这是一个已经过期的字符串类型。在 es5 之前,用这个来描述字符串,现在的话,它已经被 text 和 keyword替代了。
  • text :如果一个字段是要被全文检索的,比如说博客内容、新闻内容、产品描述,那么可以使用text。用了 text
    之后,字段内容会被分析,在生成倒排索引之前,字符串会被分词器分成一个个词项。text类型的字段不用于排序,很少用于聚合。这种字符串也被称为 analyzed 字段。
  • keyword :这种类型适用于结构化的字段,例如标签、email地址、手机号码等等,这种类型的字段可以用作过滤、排序、聚合等。这种字符串也称之为 not-analyzed 字段。

2.2、数字类型

类型 取值范围
long -2^63到2^63-1
integer -2^31到2^31-1
short -2^15到2^15-1
byte -2^7到2^7-1
double 64位的双精度IEEE754浮点类型
float 32位的双精度IEEE754浮点类型
half_float 16位的双精度IEEE754浮点类型
scaled_float 缩放类型的浮点类型
  • 在满足需求的情况下,优先使用范围小的字段。字段长度越短,索引和搜索的效率越高。
  • 浮点数,优先考虑使用 scaled_float。

scaled_float 举例:

    PUT /product
    {
      "mappings": {
        "properties": {
          "name": {
            "type": "text"
          },
          "price": {
            "type": "scaled_float",
            "scaling_factor": 100
          }
        }
      }
    }

2.3、日期类型

由于 JSON 中没有日期类型,所以 es 中的日期类型形式就比较多样:

  • 2020-11-11 或者 2020-11-11 11:11:11
  • 一个从 1970.1.1 零点到现在的一个秒数或者毫秒数。

es 内部将时间转为 UTC,然后将时间按照 millseconds-since-the-epoch 的长整型来存储。

自定义日期类型:

    PUT /product
    {
      "mappings": {
        "properties": {
          "date": {
            "type": "date"
          }
        }
      }
    }

这个能够解析出来的时间格式比较多:

    PUT /product/_doc/1
    {
      "date": "2020-11-11"
    }
    
    PUT /product/_doc/2
    {
      "date": "2020-11-11T11:11:11Z"
    }
    
    PUT /product/_doc/3
    {
      "date": "1604672099958"
    }

上面三个文档中的日期都可以被解析,内部存储的是毫秒计时的长整型数。

2.4、布尔类型(boolean)

JSON 中的 “true”、“false”、true、false 都可以。

2.5、二进制类型(binary)

二进制接受的是 base64 编码的字符串,默认不存储,也不可以搜索。

    PUT /img 
    {
      "mappings": {
        "properties": {
          "icon": {
            "type": "binary"
          }
        }
      }
    }

2.6、范围类型

integer_range 一个带符号的32位整数范围,最小值为,最大值为。
integer_range 一个带符号的32位整数范围,最小值为,最大值为。
float_range 一系列单精度32位IEEE754浮点值。
long_range 一系列带符号的64位整数,最小值为-2的63次方,最大值为2的63次方-1。
double_range 一系列双精度64位IEEE754浮点值。
date_range 自系 EPOCH 以来经过的一系列日期值,表示为无符号的64位整数毫秒。
ip_range 支持IPv4或IPv6(或混合)地址的一系列ip值。

定义的时候,指定范围类型即可:

    PUT range_index
    {
      "mappings": {
        "properties": {
          "expected_attendees": {
            "type": "integer_range"
          },
          "time_frame": {
            "type": "date_range", 
            "format": "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis"
          }
        }
      }
    }

新增一个文档:

    PUT range_index/_doc/1?refresh
    {
      "expected_attendees" : { 
        "gte" : 10,
        "lte" : 20
      },
      "time_frame" : { 
        "gte" : "2015-10-31 12:00:00", 
        "lte" : "2015-11-01"
      }
    }

在上面的文档中,我们输入了两个 range 的数据,它们分别对应我们之前在 mapping 中定义的 integer_range 及 date_range。

下面我们可以使用一个 term query 来查询 integer_range 字段 expected_attendees:

    GET range_index/_search
    {
      "query": {
        "term": {
          "expected_attendees": {
            "value": "10"
          }
        }
      }
    }

返回:

    {
      "took" : 6,
      "timed_out" : false,
      "_shards" : {
        "total" : 1,
        "successful" : 1,
        "skipped" : 0,
        "failed" : 0
      },
      "hits" : {
        "total" : {
          "value" : 1,
          "relation" : "eq"
        },
        "max_score" : 1.0,
        "hits" : [
          {
            "_index" : "range_index",
            "_type" : "_doc",
            "_id" : "1",
            "_score" : 1.0,
            "_source" : {
              "expected_attendees" : {
                "gte" : 10,
                "lte" : 20
              },
              "time_frame" : {
                "gte" : "2015-10-31 12:00:00",
                "lte" : "2015-11-01"
              }
            }
          }
        ]
      }
    }

因为 10 刚好是在我们之前的文档定义的 10-20 区间。为了验证我们的搜索是否有效,我们可以做另外的一个搜索:

    GET range_index/_search
    {
      "query": {
        "term": {
          "expected_attendees": {
           
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值