美文网首页
015.Elasticsearch Mapping介绍

015.Elasticsearch Mapping介绍

作者: CoderJed | 来源:发表于2020-06-30 15:36 被阅读0次

    1. mapping解析

    1.1 mapping是什么

    • mapping,就是index的type的元数据,每个type都有一个自己的mapping,决定了这个type的数据类型,建立倒排索引的行为,还有进行搜索的行为,可以类比关系型数据库,ES给某个index的type设置mapping,就相当于给一张表定义各个字段的名称和数据类型
    • 往一个不存在的index里面插入数据,es会自动建立该index,同时建立type以及对应的mapping
    • mapping中就自动定义了每个field的数据类型
    • es可以进行dynamic mapping,自动建立mapping,包括自动设置数据类型;也可以提前手动创建index和type的mapping,对各个field进行设置,包括数据类型,包括索引行为,包括分词器,等等

    1.2 创建mapping

    为空index设置mapping,index需要提前创建好

    # ES6.x需要在_mapping后指定type,type可以自动创建
    curl -X PUT "node01:9200/nba/_mapping/_doc" -H 'Content-Type:application/json' -d'
    {
        "properties": {
            "name": {
                "type": "text"
            },
            "team_name": {
                "type": "text"
            },
            "position": {
                "type": "keyword"
            },
            "play_year": {
                "type": "keyword"
            },
            "jerse_no": {
                "type": "keyword"
            }
        }
    }
    '
    
    # ES7.x
    curl -X PUT "node01:9200/nba/_mapping" -H 'Content-Type:application/json' -d'
    {
        "properties": {
            "name": {
                "type": "text"
            },
            "team_name": {
                "type": "text"
            },
            "position": {
                "type": "keyword"
            },
            "play_year": {
                "type": "keyword"
            },
            "jerse_no": {
                "type": "keyword"
            }
        }
    }
    '
    

    创建index的时候设置mapping

    # ES6.x
    curl -X PUT "node01:9200/index4" -H 'Content-Type:application/json' -d'
    {
      "mappings": {
        "test_type": {
          "properties": {
            "id": {
              "type": "text"
            }
          }
        }
      }
    }
    '
    # ES7.x
    curl -X PUT "node01:9200/index4" -H 'Content-Type:application/json' -d'
    {
      "mappings": {
        "properties": {
          "id": {
          "type": "text"
          }
        }
      }
    }
    '
    

    1.3 查看mapping

    查看某个索引的mapping

    # ES6.0需要指定type
    curl -X GET "node01:9200/nba/_mapping/_doc"
    # ES7.0不需要指定type
    curl -X GET "node01:9200/nba/_mapping"
    
    {
        "nba": {
            "mappings": {
                "_doc": {
                    "properties": {
                        "jerse_no": {
                            "type": "keyword"
                        },
                        "name": {
                            "type": "text"
                        },
                        "play_year": {
                            "type": "keyword"
                        },
                        "position": {
                            "type": "keyword"
                        },
                        "team_name": {
                            "type": "text"
                        }
                    }
                }
            }
        }
    }
    

    查看多个索引或者type的mapping

    • ES5.x:一个index可以有多个type

      • 查看一个index的一个type的mapping:curl -X GET "ip:9200/index/_mapping/type"

      • 查看一个index的多个type的mapping:curl -X GET "ip:9200/index/_mapping/type1,type2"

      • 查看一个index的所有type的mapping:curl -X GET "ip:9200/index/_mapping"

      • 查看多个index的多个type的mapping:curl -X GET "ip:9200/index1,index2/_mapping/type1,type2"

        这时会做笛卡尔积,把所有可以查到的index的type的mapping返回

      • 可以使用通配符:

        curl -X GET "ip:9200/index*,test*/_mapping"

        curl -X GET "ip:9200/*1,*2/_mapping/type*"

        使用通配符也会做笛卡尔积,所有满足通配符的index和type,只要可以这个index有这个type就会查出mapping并返回

    • ES6.x:一个index只能有一个type

      • 查看一个index的mapping

        curl -X GET "ip:9200/index/_mapping/type"

        curl -X GET "ip:9200/index/_mapping"

        由于只有一个type,所以这两条查询本质上是一样的

      • 查看多个index的mapping

        curl -X GET "ip:9200/index1,index2/_mapping/type1,type2"

        curl -X GET "ip:9200/test*/_mapping"

        同样,也是做笛卡尔积,只要可以查出来就返回

    • ES7.x:没有type的概念

      • 查看多个index的mapping:

        curl -X GET "ip:9200/index1,index2/_mapping"

        curl -X GET "ip:9200/test*/_mapping"

    • ES6.x测试

      index和type对应关系:

      test_index1/test_type1

      test_index2/test_type2

      curl -X GET "node01:9200/test_index1/_mapping"
      {
        "test_index1":{
            "mappings":{
                "test_type1":{
                    "properties":{
                        "name":{
                            "type":"text"
                        }
                    }
                }
            }
        }
      }
      
      curl -X GET "node01:9200/test_index1/_mapping/test_type1"
      {
        "test_index1":{
            "mappings":{
                "test_type1":{
                    "properties":{
                        "name":{
                            "type":"text"
                        }
                    }
                }
            }
        }
      }
      
      curl -X GET "node01:9200/test_index1,test_index2/_mapping"
      { "test_index2":{
            "mappings":{
                "test_type2":{
                    "properties":{
                        "name":{
                            "type":"text"
                        }
                    }
                }
            }
        },
        "test_index1":{
            "mappings":{
                "test_type1":{
                    "properties":{
                        "name":{
                            "type":"text"
                        }
                    }
                }
            }
        }
      }
      
      curl -X GET "node01:9200/test_index1,test_index2/_mapping/test_type1"
      {
        "test_index1":{
            "mappings":{
                "test_type1":{
                    "properties":{
                        "name":{
                            "type":"text"
                        }
                    }
                }
            }
        }
      }
      
      curl -X GET "node01:9200/test_index1,test_index2/_mapping/test_type2"
      {
        "test_index2":{
            "mappings":{
                "test_type2":{
                    "properties":{
                        "name":{
                            "type":"text"
                        }
                    }
                }
            }
        }
      }
      
      curl -X GET "node01:9200/test_index1,test_index2/_mapping/test_type1,test_type2"
      { "test_index2":{
            "mappings":{
                "test_type2":{
                    "properties":{
                        "name":{
                            "type":"text"
                        }
                    }
                }
            }
        },
        "test_index1":{
            "mappings":{
                "test_type1":{
                    "properties":{
                        "name":{
                            "type":"text"
                        }
                    }
                }
            }
        }
      }
      
      curl -X GET "node01:9200/test_index*,index*/_mapping"
      {
        "index3":{
            "mappings":{}
        },
        "test_index":{
            "mappings":{
                "test_type":{
                    "properties":{
                        "message":{
                            "type":"text",
                            "fields":{
                                "keyword":{
                                    "type":"keyword",
                                    "ignore_above":256
                                }
                            }
                        },
                        "user":{
                            "type":"text",
                            "fields":{
                                "keyword":{
                                    "type":"keyword",
                                    "ignore_above":256
                                }
                            }
                        }
                    }
                }
            }
        },
        "test_index2":{
            "mappings":{
                "test_type2":{
                    "properties":{
                        "name":{
                            "type":"text"
                        }
                    }
                }
            }
        },
        "index2":{
            "mappings":{}
        },
        "index1":{
            "mappings":{
                "_doc":{
                    "properties":{
                        "jerse_no":{
                            "type":"keyword"
                        },
                        "name":{
                            "type":"text"
                        },
                        "play_year":{
                            "type":"keyword"
                        },
                        "position":{
                            "type":"keyword"
                        },
                        "team_name":{
                            "type":"text"
                        }
                    }
                }
            }
        },
        "test_index1":{
            "mappings":{
                "test_type1":{
                    "properties":{
                        "name":{
                            "type":"text"
                        }
                    }
                }
            }
        }
      }
      

    查看全部索引的mapping

    • ES5.x/ES6.x

      • 查看所有的index的所有的type的mapping

        curl -X GET "ip:9200/_mapping

      • 查看所有的index的某些type的mapping,没有这个type的index,就不返回它的mapping

        curl -X GET "ip:9200/_all/_mapping/type1,type2

    • ES7.x

      curl -X GET "ip:9200/_mapping"

      curl -X GET "ip:9200/_all/_mapping"

    • ES6.x测试

      curl -X GET node01:9200/_all/_mapping/test_type1,test_type2
    {
          "test_index2": {
              "mappings": {
                  "test_type2": {
                      "properties": {
                          "name": {
                              "type": "text"
                          }
                      }
                  }
              }
          },
          "test_index1": {
              "mappings": {
                  "test_type1": {
                      "properties": {
                          "name": {
                              "type": "text"
                          }
                      }
                  }
              }
          }
      }
      
      curl -X GET node01:9200/_mapping
      {
          "index1": {
              "mappings": {
                  "_doc": {
                      "properties": {
                          "jerse_no": {
                              "type": "keyword"
                          },
                          "name": {
                              "type": "text"
                          },
                          "play_year": {
                              "type": "keyword"
                          },
                          "position": {
                              "type": "keyword"
                          },
                          "team_name": {
                              "type": "text"
                          }
                      }
                  }
              }
          },
          "index2": {
              "mappings": {}
          },
          "test_index2": {
              "mappings": {
                  "test_type2": {
                      "properties": {
                          "name": {
                              "type": "text"
                          }
                      }
                  }
              }
          },
          "test_index": {
              "mappings": {
                  "test_type": {
                      "properties": {
                          "message": {
                              "type": "text",
                              "fields": {
                                  "keyword": {
                                      "type": "keyword",
                                      "ignore_above": 256
                                  }
                              }
                          },
                          "user": {
                              "type": "text",
                              "fields": {
                                  "keyword": {
                                      "type": "keyword",
                                      "ignore_above": 256
                                  }
                              }
                          }
                      }
                  }
              }
          },
          "test2": {
              "mappings": {}
          },
          "nba": {
              "mappings": {
                  "_doc": {
                      "properties": {
                          "jerse_no": {
                              "type": "keyword"
                          },
                          "name": {
                              "type": "text"
                          },
                          "play_year": {
                              "type": "keyword"
                          },
                          "position": {
                              "type": "keyword"
                          },
                          "team_name": {
                              "type": "text"
                          }
                      }
                  }
              }
          },
          "test_index1": {
              "mappings": {
                  "test_type1": {
                      "properties": {
                          "name": {
                              "type": "text"
                          }
                      }
                  }
              }
          },
          "test1": {
              "mappings": {}
          },
          "index3": {
              "mappings": {}
          }
      }
    

    1.4 修改mapping

    # 只能新增field,不能修改已有field的数据类型
    curl -X PUT "node01:9200/test_index1/_mapping/test_type1" -H 'Content-Type:application/json' -d'
    {
        "properties": {
            "id": {
                "type": "text"
            }
        }
    }
    '
    
    # 如果要写上原有的字段,一定要和以前的数据类型一样
    curl -X PUT "node01:9200/test_index1/_mapping/test_type1" -H 'Content-Type:application/json' -d'
    {
        "properties": {
            "id": {
                "type": "text"
            },
            "name": {
                "type": "text"
            }
        }
    }
    '
    
    # EX7.x不需要指定type
    curl -X PUT "node01:9200/test_index1/_mapping" -H 'Content-Type:application/json' -d'
    {
        "properties": {
            "id": {
                "type": "text"
            }
        }
    }
    '
    

    1.5 mapping其他常用属性总结

    PUT index_name
    {
      "mappings": {
        "type_name": {
          "_source": {
              "enabled": true
          },
          "_all": {
              "enabled": true
          },
          "dynamic": "strict",
          "date_detection": false,
          "properties": {
              "field_name": {
                  "type": "type_name", # 指定field的数据类型
                  "analyzer": "analyzer_name", # 指定field的分词器
                  "include_in_all": false # 这个field是否包含在_all field中
              }
          }
        }
      }
    }
    
    • _all:是否允许将所有field的值拼接在一起,作为一个_all field,建立索引,这样在没有指定任何field进行搜索时,就是使用_all field在搜索,默认true

    • _source:是否保存原始数据,开启后可以带来以下好处,默认开启:

      (1) ES搜索默认只会返回id,当_source=false时,需要根据返回的id再去查询一次完整的数据,_source=true时,可以直接拿到完整的数据

      (2) ES的更新操作基于_source实现

      (3) 索引的重建必须要有_source

      (4) 可以基于_source自定义返回的field

      (5) 方便于debug

      如果不需要上述好处,可以禁用_source

    • dynamic:自动判断数据类型的策略

      true:如果document的某个field没有提前设置其类型,就自动识别

      false:如果document的某个field没有提前设置其类型,就忽略此field,数据可以插入进去,但在mapping中查不到此field的描述

      strict:如果document的某个field没有提前设置其类型,直接报错

    • date_detection:默认会自动按照一定格式识别date,比如yyyy-MM-dd,这样可能会导致一些问题,比如某个field先插入的值为"2017-01-01",那么这个field会自动识别为date类型,后面再插入一个其他类型,例如字符串"hello world"之类的值,就会报错。可以关闭date_detection,如果有需要,手动指定某个field为date类型就可以避免此类问题。

    1.6 mapping模板

    # 定制化type级别的mapping模板
    # 此模板的意思:
    # 假如插入的数据的field的名称中包含"title"这个单词,就将其value设置为text类型,且使用ik_max_word分词器分词
    # 其他的field则使用dynamic设置的策略来进行数据类型和分词器的初始化
    PUT index_name
    {
      "mappings": {
        "type_name": {
          "dynamic_templates": [
            {
              "template_name": {
                "match": "*title*",
                "match_mapping_type": "text",
                "mapping": {
                  "type": "text",
                  "analyzer": "ik_max_word"
                }
              }
            }
          ] 
        }
      }
    }
    
    # 定制化index级别的mapping模板
    # 此模板的意思:
    # blog这个这个type的_all=true,其他type的_all=false
    PUT my_index
    {
      "mappings": {
        "_default_": {
          "_all": { "enabled": false}
        },
        "blog": {
          "_all": { "enabled": true}
        }
      }
    }
    

    2.ES常用的数据类型

    2.1 核心数据类型

    • 字符串

      • text:用于全文检索,该类型的字段将通过分词器进行分词
      • keyword:不分词,只能搜索该字段的完整的值
    • 数值型

      • byte

      • short

      • integer

      • long

      • float

      • half_float

      • scaled_float

      • double

    • 布尔

      • boolean
    • 二进制

      • binary:该类型的字段把值当作经过BASE64编码的字符串,默认不存储且不可搜索
    • 日期

      • date,定义的类型是date,实际需要传入一个字符串或者long值,只要这个字符串满足日期格式,例如"yyyy-MM-dd"或者"yyyy/MM/dd HH:mm:ss",或者这个long值是一个时间戳,就认为是date类型
    • 范围类型

      • integer_range、double_range等数值范围

      • date_range

      • 例如定义age是一个integer_range

        {
            "gte": 20,
            "lte": 40
        }
        

    2.2 复杂数据类型

    • Object:对象类型,可以嵌套
    • Array:ES中没有专有的数组类型,使用[]直接定义即可,数组中的元素必须都是同一类型
      • 字符串数组:["hello", "world"]
      • 整数数组:[0, 1]
      • 对象数组:[{"name": "Tom", "age": 12}, {"name": "Jerry", "age": 20}]

    3. type底层存储

    type,是一个index中用来区分类似的数据的,类似的数据,但是可能有不同的fields,而且有不同的属性来控制索引建立和分词等功能,ES底层的lucene是没有type的概念的,在document中,实际上将type作为一个document的特殊field来存储,即_type,ES通过_type来进行type的过滤和筛选,一个index中的多个type,实际上是放在一起存储的,因此一个index下,type名相同的document,其数据结构和其他设置一定是一样的。

    例如以下index:

    # 注意:此语句在ES6.x和ES7.x是不能执行的,因为ES6.x只能有一个type,ES7.x移除了type的概念
    PUT /my_index
    {
      "mappings": {
        "my_type1": {
          "properties": {
            "name": {
              "type": "keyword"
            },
            "age": {
              "type": "long"
            }
          }
        },
        "my_type2": {
          "properties": {
            "name": {
              "type": "keyword"
            },
            "sex": {
              "type": "long"
            }
          }
        }
      }
    }
    
    # 插入两条document
    PUT /my_index/my_type1/1
    {
      "name": "Tom",
      "age": 20
    }
    
    PUT /my_index/my_type2/2
    {
      "name": "Jerry",
      "sex": 1
    }
    
    # 实际的存储为:
    {
      "_type": "my_type1"
      "name": "Tom",
      "age": 20,
      "sex": null
    }
    {
      "_type": "my_type2"
      "name": "Jerry",
      "age": null,
      "sex": 1
    }
    

    说明:如果使用ES5.x版本,且在同一个index中使用多个type,那么将类似结构的type放在一个index下,这些type应该有多个field是相同的,假如两个type的field完全不同,却放在一个index下,那么就每条数据都会有很多的空值,会带来严重的性能问题。

    相关文章

      网友评论

          本文标题:015.Elasticsearch Mapping介绍

          本文链接:https://www.haomeiwen.com/subject/xmkxqktx.html