• 【Elasticsearch教程4】Mapping 动态映射


    一、动态映射

    刚开始学ES时感觉它与MySQL相比,有个明显不同:ES不需要先定义表结构就可以插入数据了。
    我们不用先创建index和mapping,直接put数据后,ES会自动帮我们创建index和mapping。
    这个功能虽然看着比较方便,但是有时也会给我们带来困扰,因为ES自动创建的mapping中的字段类型不一定是我们期望的。所以掌握好ES的Mapping的知识是在工作中使用ES的基础。

    ES的mappings设置选项中,有个dynamic,它是控制是否接收以及如何处理新的字段,它有四个值可选:

    PUT pigg_map_test
    {
      "mappings": {
        "dynamic": runtime
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    dynamic值说明
    true添加新字段到mapping中,这个是默认值
    runtime新字段将作为runtime fields添加到mapping,这些字段不会被索引,查询时会从_source中加载出来
    false新添加的字段会被忽略,这些新字段不会被索引,所以也不支持检索
    strict严格模式,当有新字段时,会报错

    这个dynamic参数一般也就采用默认值true。它有2个优点:

    • 容错率高,即使没有为新字段设置mapping,也会存储,哪怕类型不对,后期可以同步到类型对的字段上,这样保证了客户的数据没有丢失。在企业开发中,丢了重要的数据可能就得提桶跑路了。
    • 别的同事来处理这个功能也比较熟悉,如果你设置成别的选项,别人再接手时可能感觉掉进一个坑里,因为他可能对这些配置并不是那么熟悉。

    注意:下面讲的动态字段映射,还是以dynamictrue的基础上继续讨论。

    二、动态字段映射

    当ES接收到新的字段,它会自动为新字段创建类型,我们要熟悉ES自动创建类型的规律。
    下面给出插入文档中JSON数据类型到ES数据类型的一个映射表。

    JSON数据类型ES数据类型
    null不添加字段
    true / falseboolean
    doublefloat
    longlong
    objectobject
    array根据数组中第一个非null值的类型
    通过日期检测的stringdate
    通过数字检测的stringfloat 或 long
    没有通过上面2个检测的string.keyword子字段的text类型

    下面我们来对上表格中每一项都依次验证下。

    1 null

    插入一个文档,name的值为null,然后再验证mapping

    PUT pigg_map_test/_doc/1
    {
      "name": null
    }
    
    • 1
    • 2
    • 3
    • 4

    GET pigg_map_test/_mapping返回如下,看出null值是不会添加字段的

    {
      "pigg_map_test" : {
        "mappings" : { }
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    2 true / false

    插入一个文档,state的值为true,然后再验证mapping

    PUT pigg_map_test/_doc/1
    {
      "state": true
    }
    
    • 1
    • 2
    • 3
    • 4

    GET pigg_map_test/_mapping返回如下,看出布尔值会设置为boolean类型

    {
      "pigg_map_test" : {
        "mappings" : {
          "properties" : {
            "state" : {
              "type" : "boolean"
            }
          }
        }
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    3 double & long 数字

    PUT pigg_map_test/_doc/1
    {
      "price": 1.0000,
      "count": 10000
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    GET pigg_map_test/_mapping返回如下:

    {
      "pigg_map_test" : {
        "mappings" : {
          "properties" : {
            "count" : {
              "type" : "long"
            },
            "price" : {
              "type" : "float"
            }
          }
        }
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    4 object

    给文档添加1个objcet

    PUT pigg_map_test/_doc/1
    {
      "user": {
        "name": "江苏最菜亚瑟",
        "salary": 33000.00
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    mapping如下,dynamictrue有这样的好处,如果设置dynamicruntime,则不会为object添加字段

    {
      "pigg_map_test" : {
        "mappings" : {
          "properties" : {
            "user" : {
              "properties" : {
                "name" : {
                  "type" : "text",
                  "fields" : {
                    "keyword" : {
                      "type" : "keyword",
                      "ignore_above" : 256
                    }
                  }
                },
                "salary" : {
                  "type" : "float"
                }
              }
            }
          }
        }
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    5 array

    插入一个数组,mapping的字段类型以第一个非null值的类型

    PUT pigg_map_test/_doc/1
    {
      "hero": [ null, 1, 2]
    }
    
    • 1
    • 2
    • 3
    • 4

    mapping如下:

    {
      "pigg_map_test" : {
        "mappings" : {
          "properties" : {
            "hero" : {
              "type" : "long"
            }
          }
        }
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    数组中数据类型得一致,下面数组同时包含1和2.2,这样文档会保存失败的

    PUT pigg_map_test/_doc/1
    {
      "hero": [ null, 1, 2.2]
    }
    
    • 1
    • 2
    • 3
    • 4

    6 时间格式的string

    关于ES的日期格式,可以参考我之前的博客详解mapping之date date_nanos
    注意第三个日期类型是yyyy-MM-ddTHH:mm:ss

    PUT pigg_map_test/_doc/1
    {
      "date1": "2022-08-25",
      "date2": "2022/08/25",
      "date3": "2022-08-25T13:25:01"
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    mapping如下,上面3个确实都转成date类型了

    {
      "pigg_map_test" : {
        "mappings" : {
          "properties" : {
            "date1" : {
              "type" : "date"
            },
            "date2" : {
              "type" : "date",
              "format" : "yyyy/MM/dd HH:mm:ss||yyyy/MM/dd||epoch_millis"
            },
            "date3" : {
              "type" : "date"
            }
          }
        }
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    6.1 定制日期格式

    我们还可以定制自己想要的日期格式,在mappings中设置dynamic_date_formats,ES会把符合格式的字符串设置为date类型。

    PUT pigg_map_test
    {
      "mappings": {
        "dynamic_date_formats": ["yyyy-MM-dd", "yyyy/MM/dd", "yyyy-MM-dd HH:mm:ss"]
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    创建文档中3个字段分别对应上面设置的3个日期格式

    PUT pigg_map_test/_doc/1
    {
      "date1": "2022-08-25",
      "date2": "2022/08/25",
      "date3": "2022-08-25 13:25:01"
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    mapping如下:

    {
      "pigg_map_test" : {
        "mappings" : {
          "dynamic_date_formats" : [
            "yyyy-MM-dd",
            "yyyy/MM/dd",
            "yyyy-MM-dd HH:mm:ss"
          ],
          "properties" : {
            "date1" : {
              "type" : "date",
              "format" : "yyyy-MM-dd"
            },
            "date2" : {
              "type" : "date",
              "format" : "yyyy/MM/dd"
            },
            "date3" : {
              "type" : "date",
              "format" : "yyyy-MM-dd HH:mm:ss"
            }
          }
        }
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    7 数字格式的string

    ES默认会把数字格式的string也设置为text类型,比如下面例子

    PUT pigg_map_test/_doc/1
    {
      "age": "30",
      "salary": "35000.00"
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    mapping中age和salary都会是text类型,如果要数字格式的字符串也按照数字格式保存,需要设置如下

    PUT pigg_map_test
    {
      "mappings": {
        "numeric_detection": true
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    再插入上面文档,会发现字段类型会是数字类型:

    {
      "pigg_map_test" : {
        "mappings" : {
          "numeric_detection" : true,
          "properties" : {
            "age" : {
              "type" : "long"
            },
            "salary" : {
              "type" : "float"
            }
          }
        }
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    三、结语

    在实际企业开发中,都会提前设置好mapping的,不会完全让ES自动设置字段类型的。但是掌握好动态字段映射还是很重要的,是学习mapping的前提条件。

    • 在字段类型比较确定时,可以先设置好mapping,再插入数据,有新字段时,先给mapping添加新的字段设置
    • 在字段的个数和类型都不确定时,可以使用mapping的动态模板,按照已经指定的规则设置它的类型。比如某个字段名为int_age,就让类型为integer,字段名为float_price就设为float

    好好学习,天天向上,下一篇博客会写mapping的动态模板的内容。

  • 相关阅读:
    浏览器发送请求的方法
    【20220902】5 tips to improve your critical thinking
    工厂模式设计思路
    源码解析HDFS文件上传之write上传过程-尚硅谷Java培训
    Debian 12快速安装图解
    java计算机毕业设计计算机实验中心网站MyBatis+系统+LW文档+源码+调试部署
    谁在领跑纯电动L2
    【leetcode】【剑指offer Ⅱ】046. 二叉树的右侧视图
    【三维重建】【深度学习】【数据集】基于COLMAP制作个人Gen6D测试数据集
    使用QLoRA对Llama 2进行微调的详细笔记
  • 原文地址:https://blog.csdn.net/winterking3/article/details/126490405