05、ES实战:映射mapping

本学习笔记基于ElasticSearch 7.10版本,旧版本已经废弃的功能暂时不做笔记,以后有涉及到再做补充。

一、映射

1.1、概念

为了能够将时间域视为时间,数字域视为数字,字符串域视为全文或精确值字符串, Elasticsearch 需要知道每个域中数据的类型。而包含数据类型的信息就放在在映射(mapping)中。

在es中,使用映射mapping来定义一个文档以及文档所包含的字段该如何被存储和索引,有点类似关系型数据库中表的定义。
我们可以在新建索引的同时定义mapping,比如上一篇中定义强制路由:

PUT routing
{
   
     
  "mappings": {
   
     
    "_routing": {
   
     
      "required": true
    }
  }
}

也可以不定义,mapping留空,后续再设置也可以。

1.2、动态映射

首先,当你增加一个新字段时,es会通过JSON中基本数据类型,尝试自动分析出字段类型和存储方式,这就是动态映射
例如我们新建一个索引,不定义mapping,然后查看索引信息:
*
可以看到mapping确实为空,现在我们往索引中添加文档:

PUT mapping_demo/_doc/1
{
   
     
  "title": "1111",
  "date": "2020-12-24"
}

现在再看看索引信息,发现mapping中自动增加了两个字段:date和title。
*
es中动态映射有以下几种:

JSON数据类型 mapping映射类型
null 不新增字段
布尔型: true 或者 false boolean
整数: 1234 long
浮点数: 123.45 double
有效日期: 2020-12-24 date
字符串 string text、keyword、date、double、long都有可能
json对象 object
数组 由数组第一个非空值决定

动态映射很方便,但有的时候也有问题,假如我们现在修改date字段内容不为日期类型,es就会返回400报错:

PUT mapping_demo/_doc/1
{
   
     
  "title": "1111",
  "date": "amby"
}

实际业务中,并非所有日期格式的数据,都需要保存为date格式。动态映射有时候也会带来不必要的麻烦,我们可以选择使用静态映射来关闭日期检测。

1.3、静态映射

静态映射,其实就是通过mappings进行配置,我们可以通过静态映射_mapping,关闭日期检测:

PUT mapping_demo/_mapping
{
   
     
  "date_detection": "false"
}

新增加两个字段:

PUT mapping_demo/_mapping
{
   
     
  "properties": {
   
     
    "name": {
   
     
      "type": "text"
    },
    "age": {
   
     
      "type": "long"
    }
  }
}

有的时候,当文档中有新字段时,希望es可以返回报错提示开发者而不是动态映射,可以通过dynamic来配置,它有三种属性值:

  • true:默认值,进行动态映射。
  • false:忽略新字段。
  • strict:严格模式,发现新字段返回400报错。
# 设置dynamic为strict严格模式
PUT mapping_demo/_mapping
{
   
     
  "dynamic": "strict"
}
# 添加未定义的新字段addr
PUT mapping_demo/_doc/2
{
   
     
  "name":"amby",
  "addr":"广州塔168层"
}

1.4、映射模板

es中动态映射并不能满足我们全部需求,而项目初期我们也不一定能通过静态映射定义所有的字段类型,这时候可以考虑通过映射模板来解决。

通过事先定义一系列的映射模板规则,让es可以按照我们的意愿进行动态映射。

1.4.1、通过字段类型映射

es默认会将整数动态映射为long类型,下面来演示一下如何通过模板映射为integer类型:

PUT blog 
{
   
     
  "mappings": {
   
     
    "dynamic_templates": [ # 通过dynamic_templates定义映射模板数组,包含多个映射模板
      {
   
     
        "long2integer": {
   
      # 映射模板名称
          "match_mapping_type": "long", # 需要映射的类型long
          "mapping": {
   
     
            "type": "integer" # 映射为integer类型
          }
        }
      }
    ]
  }
}
# 添加整数文档
PUT blog/_doc/1
{
   
     
  "number": 99
}

接下来使用 GET blog 查看索引结构,可以看到number字段已经映射为integer类型:
*

1.4.2、通过字段名映射

也可以通过定义字段名称规则来动态映射:

PUT blog 
{
   
     
  "mappings": {
   
     
    "dynamic_templates": [
      {
   
     
        "string2long": {
   
     
          "match_mapping_type": "string", # 仅处理字符串类型
          "match": "num_*", # num_前缀的字符串映射为integer
          "unmatch": "*_text", # _text后缀的字符串不映射
          "mapping": {
   
     
            "type": "integer"
          }
        }
      }
    ]
  }
}
PUT blog/_doc/1
{
   
     
  "num_count": "99", # 有num_前缀,会映射为integer
  "num_text": "amby", # 有_text后缀,不会映射为integer
  "num_aaa": 99 # 虽然有num_前缀,但数据类型不是字符串,不会映射为integer
}

查看索引结构,映射结果符合预期:
*

参考官方文档:
https://www.elastic.co/guide/cn/elasticsearch/guide/current/mapping-intro.html

版权声明:

本文仅记录ElasticSearch学习心得,如有侵权请联系删除。
更多内容请访问原创作者:江南一点雨
*

版权声明:本文不是「本站」原创文章,版权归原作者所有 | 原文地址: