动态映射好处就在于我们不需要创建索引,直接创建文档的时候 elasticsearch 就帮助我们创建了索引。dynamic 有三个属性 true / runtime / strict / false, 其中 trueruntime 这两个属性的 object / array / string 检测的类型略有不同,可以查看官方文档。

正常情况下,date 类型是自动检测的,而 Numeric 类型的自动检测却是关闭的

POST /test/_doc/1
{
  "create_date":"2023-09-01",
  "number": "1"
}

GET test/_mapping
生成的 mapping 如下
{
  "test": {
    "mappings": {
      "properties": {
        "create_date": {
          "type": "date"
        },
        "number": {
          "type": "text",
          "fields": {
            "keyword": {
              "type": "keyword",
              "ignore_above": 256
            }
          }
        }
      }
    }
  }
}
这里我们就看到了,当我们输入 string 类型的数字的时候,自动给我们映射成了 text 类型,这时候我们可以使用 numeric_detection 来开启自动检测。而且我们可以通过使用 dynamic_date_formats
# 删除上面创建的索引
DELETE test

# 设置映射检测
PUT test
{
    "mappings":
    {
        "date_detection":true,
        "numeric_detection":true,
        "dynamic_date_formats": "yyyy-MM-dd||yyyy/MM/DD||yyyy/MM"
    }
}

# 写入数据
POST /test/_doc/1
{
    "create_date":"2023-09-01",
    "number": "1"
}

GET test/_mapping
生成的 mapping 如下
{
  "test": {
    "mappings": {
      "dynamic_date_formats": [
        "yyyy-MM-dd||yyyy/MM/DD||yyyy/MM"
      ],
      "date_detection": true,
      "numeric_detection": true,
      "properties": {
        "create_date": {
          "type": "date",
          "format": "yyyy-MM-dd||yyyy/MM/DD||yyyy/MM"
        },
        "number": {
          "type": "long"
        }
      }
    }
  }
}

动态映射模板 Dynamic templates

{name}{dynamic_type} 分别是字段名称和检测类型的占位符。 match_mapping_type 是动态数据类型检测,matchunmatch 作为字段名称的匹配,而 path_matchpath_unmatch 是在节点路径上进行匹配。(动态字段映射只能是字段有具体值时候才会生效,如果字段是 null 或者空数组时候不会添加动态字段映射)
# 删除之前的索引
DELETE test

# 创建动态映射
PUT test
{
  "mappings": {
    "dynamic_templates":[
      {
        "string_as_ip":{
          "match_mapping_type":"string",
          "match":"ip_*", # 匹配 ip_开头的
          "unmatch":"*_ip", # 不检测以 _ip 结尾的
          "runtime":{   
            "type":"ip" # 因为 ip 不是动态属性,所以这里我们使用 runtime
          }
        }
      },
      {
        "long_as_integers":{
          "match_mapping_type":"long", # 匹配long类型
          "unmatch":"*_long", # 不检测以 _long 结尾
          "mapping":{
            "type":"integer" # 映射成 integer 类型
          }
        }
      },
      {
        "full_name":{
          "path_match":"name.*", # 匹配 name. 路径的字段
          "path_unmatch":"*.middle", # 不匹配 .middle 路径的字段
          "mapping":{
            "norms": false, # 禁用 norms,不排序打分 
            "type":"text",
            "copy_to":"full_name"
          }
        }
      },
      {
        "no_doc_values":{
          "match_mapping_type":"boolean", # 匹配 boolean 类型
          "mapping":{
            "type":"{dynamic_type}", # 这里只是演示,让他还映射成 boolean 类型
            "doc_values":false,
            "index":false # 禁用索引
          }
        }
      }
    ]
  }
}

# 写入测试数据
POST test/_doc/1
{
  "ip_v4":"127.0.0.1",
  "v6_ip":"FC00:0000:130F:0000:0000:09C0:876A:130B",
  "count":5,
  "name":{
    "firstname":"first",
    "middlename":"middle",
    "lastname":"last"
  },
  "bool":false
}

# 获取 mapping
GET test/_mapping
mapping 输出结果如下:
{
  "test": {
    "mappings": {
      "dynamic_templates": [
        {
          "string_as_ip": {
            "match": "ip_*",
            "unmatch": "*_ip",
            "match_mapping_type": "string",
            "runtime": {
              "type": "ip"
            }
          }
        },
        {
          "long_as_integers": {
            "unmatch": "*_long",
            "match_mapping_type": "long",
            "mapping": {
              "type": "integer"
            }
          }
        },
        {
          "full_name": {
            "path_match": "name.*",
            "path_unmatch": "*.middle",
            "mapping": {
              "copy_to": "full_name",
              "norms": false,
              "type": "text"
            }
          }
        },
        {
          "no_doc_values": {
            "match_mapping_type": "boolean",
            "mapping": {
              "doc_values": false,
              "index": false,
              "type": "{dynamic_type}"
            }
          }
        }
      ],
      "runtime": {
        "ip_v4": {
          "type": "ip"
        }
      },
      "properties": {
        "bool": {
          "type": "boolean",
          "doc_values": false,
          "index": false
        },
        "count": {
          "type": "integer"
        },
        "full_name": {
          "type": "text",
          "fields": {
            "keyword": {
              "type": "keyword",
              "ignore_above": 256
            }
          }
        },
        "name": {
          "properties": {
            "firstname": {
              "type": "text",
              "copy_to": [
                "full_name"
              ],
              "norms": false
            },
            "lastname": {
              "type": "text",
              "copy_to": [
                "full_name"
              ],
              "norms": false
            },
            "middlename": {
              "type": "text",
              "copy_to": [
                "full_name"
              ],
              "norms": false
            }
          }
        },
        "v6_ip": {
          "type": "text",
          "fields": {
            "keyword": {
              "type": "keyword",
              "ignore_above": 256
            }
          }
        }
      }
    }
  }
}
技巧:当我们要创建一个 index 指定 mapping 时(explicit mapping),我们可以先通过现在有的数据来添加到文档,然后查看文档的 mapping 复制后再修改 mapping 可以省去你很多的工作。
# 举例
PUT my-create-index 
{
    "username": "test create",
    "age": 20,
    "sex": "man",
    "phone": "188......",
    .....  # 此处省略 N多字段
}

# 然后获取 mapping
GET my-create-index

# 通过返回的 mapping 我们删除 index 然后重建就可以了

DELETE my-create-index

PUT my-create-index
{
    ..... # 复制的上边生成的然后根据自己的需求在微调
}

点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论
立即
投稿

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部