Dynamic mapping

简介

自动检测和添加新字段称为动态映射。 动态映射规则可以根据你的目的进行定制

  • 动态字段映射:管理动态 field 检测的规则

  • 动态模板:用于配置动态添加字段的映射的自定义规则

动态模板

适用场景

  • 在映射定义时未知的动态字段名称的文档

  • nested 的 key/value 对

语法

"dynamic_templates": [
    {
      "my_template_name": {   (1)
        ...  match conditions ...  (2) 
        "mapping": { ... }  (3)
      }
    },
    ...
  ]
  1. template 的名字可以是任何一个字符串
  2. 匹配的条件可以是任何一种 match_mapping_type, match,match_pattern, unmatch,path_match, path_unmatch
  3. 被匹配的字段的 mapping

案例

将所有整数字段映射为integer而不是 long,并将所有字符串字段映射为 text 和 keyword

PUT my_index
{
  "mappings": {
    "dynamic_templates": [
      {
        "integers": {
          "match_mapping_type": "long",
          "mapping": {
            "type": "integer"
          }
        }
      },
      {
        "strings": {
          "match_mapping_type": "string",
          "mapping": {
            "type": "text",
            "fields": {
              "raw": {
                "type":  "keyword",
                "ignore_above": 256
              }
            }
          }
        }
      }
    ]
  }
}
 
PUT my_index/_doc/1
{
  "my_integer": 5, 
  "my_string": "Some string" 
}

通过上面的动态 template 映射,可以看到 my_integer 被映射为 integer 而不是 long。my_string 是一个 multi_field 字段。

假设你希望任何未映射的字符串字段默认情况下映射为 “keyword” 类型,可以定义如下

PUT test2
{
  "mappings": {
    "dynamic_templates": [
      {
        "my_string_fields": {
          "match_mapping_type": "string",
          "mapping": {
            "type": "keyword"
          }
        }
      }
    ]
  }
}

match及unmatch

match 参数使用模式匹配字段名称,而 unmatch 使用模式排除匹配的字段。

案例

匹配名称以 long_ 开头的所有字符串字段(以_text结尾的字符串除外)并将它们映射为长字段

PUT my_index
{
  "mappings": {
    "dynamic_templates": [
      {
        "longs_as_strings": {
          "match_mapping_type": "string",
          "match":   "long_*",
          "unmatch": "*_text",
          "mapping": {
            "type": "long"
          }
        }
      }
    ]
  }
}
 
PUT my_index/_doc/1
{
  "long_num": "5", 
  "long_text": "foo" 
}

查看数据类型

GET my_index/_mapping

结果显示

{
  "my_index" : {
    "mappings" : {
      "dynamic_templates" : [
        {
          "longs_as_strings" : {
            "match" : "long_*",
            "unmatch" : "*_text",
            "match_mapping_type" : "string",
            "mapping" : {
              "type" : "long"
            }
          }
        }
      ],
      "properties" : {
        "long_num" : {
          "type" : "long"
        },
        "long_text" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        }
      }
    }
  }
}

上面结果显示,long_num 的数据类型是 long,而 long_text 的数据类型是 text。

控制动态字段

默认情况下,在文档中找到以前未见过的字段时,Elasticsearch 会将新字段添加到类型映射中。 通过将 dynamic 参数设置为 false(忽略新字段)或 strict(如果遇到未知字段则抛出异常),可以在文档和对象级别禁用此行为。

在生产(product) 环境中,你极有可能会创建你的 mapping 在索引你的数据之前,而且你极有可能不想你的 mapping 会被修改

dynamic属性

取值doc indexed?fields indexed?mapping indexed?
trueYesYesYes
falseYesNoNo
strictNo
  • 在 dynamic 为 true 时,这个文档将被建立索引,从而新增加的字段将是可以被搜索及应用于聚合,mapping 也会自动更新
  • 在 dynamic 为 false 时,这个文档将被建立索引,但是新的字段将不被建立索引,mapping 将不被更新(包含新的字段的mapping)
  • 在 dynamic 为 strict 时,这个文件将不被建立索引

案例

PUT blogs_example/_mapping
{
  "dynamic": "strict"
}

上述设置表明如果现有的 mapping 里没有定义这个字段,那么就不 index 这个文档。

PUT /blogs_example/_doc/1
{
  "new_field": "this is a new field"
}

如果new_field从来没有在mapping中定义过,那么,上面的命令会出现如下的错误

{
  "error": {
    "root_cause": [
      {
        "type": "strict_dynamic_mapping_exception",
        "reason": "mapping set to strict, dynamic introduction of [new_field] within [_doc] is not allowed"
      }
    ],
    "type": "strict_dynamic_mapping_exception",
    "reason": "mapping set to strict, dynamic introduction of [new_field] within [_doc] is not allowed"
  },
  "status": 400
}

如果这个问题出现了,必须修改现有的 index 的 mapping

PUT blogs_example/_mapping
{
  "properties": {
    "new_field": {
      "type": "text"
    }
  }
}

settings防止映射爆炸

在索引中定义太多字段是一种可能导致映射爆炸的情况,这可能导致内存不足的错误和难以恢复的情况。这个问题可能比预期更常见。例如,考虑插入的每个新文档引入新字段的情况。这在动态映射中非常常见。每次文档包含新字段时,这些字段最终都会出现在索引的映射中。这并不需要担心少量数据,但随着映射的增加,它可能会成为一个问题。以下设置允许你限制可手动或动态创建的字段映射的数量,以防止错误的文档导致映射爆炸。

index.mapping.total_fields.limit

索引中的最大字段数。字段和对象映射以及字段别名都计入此限制。默认值为1000

index.mapping.depth.limit

字段的最大深度,以内部对象的数量来衡量。例如,如果所有字段都在根对象级别定义,则深度为1。如果有一个对象映射,则深度为2,等等。默认值为20。

index.mapping.nested_fields.limit

索引中不同 nested 映射的最大数量,默认为50。

index.mapping.nested_objects.limit

所有 nested 类型中单个文档中嵌套 JSON 对象的最大数量,默认为10000。

index.mapping.field_name_length.limit

设置字段名称的最大长度。默认值为 Long.MAX_VALUE(无限制)。此设置实际上不是解决映射爆炸的问题,但如果要限制字段长度,则可能仍然有用。 通常不需要设置此设置。默认是可以的,除非用户开始添加大量具有真正长名称的字段。

上面的字段都可以在一个 index 的设置中进行设置,比如

PUT test_blog 
{
  "settings": {
    "index.mapping.total_fields.limit": 2000,
    "number_of_replicas": 0,
    "number_of_shards": 1
  }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值