Dynamic Mapping(动态映射)

官方地址
Elasticsearch 最重要的功能之一就是让你尽可能快地开始探索数据。要索引文档,你不用立即创建 index(索引),定义相关的 mapping type(映射类型)和定义相关的 fields(字段)— 你可以直接使用索引 document(文档)、index(索引)、type(类型)和 fields(字段),这些操作都将自动生效。

PUT data/_doc/1 
{ "count": 5 }

上面这个例子会自动创建名为 data 的索引,其中包含名为 _doc 的 mapping type(映射类型),以及名为 count 的 long 数据类型。
自动的检测和添加新的类型以及字段的过程,称之为动态映射。你可以根据需要定制动态映射的规则:
Dynamic field mappings(动态字段映射):控制动态字段发现的规则。
Dynamic templates(动态模板):利用自定义规则来配置动态添加的字段的映射。

无论是自动还是显式的创建索引,Index templates(索引模板)都允许你为一个新的索引配置 mappings,settings 和 aliases(别名)。

Dynamic field mapping(动态字段映射)

默认情况下,当文档中出现以前没有出现过的字段时,Elasticsearch会将新的字段添加到类型映射中。动态映射可以被禁用,既可以整体禁用也可以对某个字段禁用。整体禁用就是是索引层面,上一篇文章讲过,在建索引的时候整体设置dynamic参数为false。还有就是可以利用coerce参数设置不能自动转换。
假设启用了动态字段映射,则有一些简单的规则来确定数据进去之后索引的数据类型:

null:不会添加这个字段
true 或者 false:boolean
浮点数:float
数:long
对象:object
数组:取决于数组里的第一个非空的值
文本:首先日期检测,看是不是日期,然后进行数值检测,看是不是double或者long,如果前面两个都不是,那就是text字段,同时会有一个名叫keyword的keyword字段。

Date detection(日期检测)

如果启动date_detection(默认),则会检查新的字符串字段,查看其内容是否与dynamic_date_formats中任一日期模式匹配。如果发现匹配,则添加一个相应格式的新的日期字段。
dynamic_date_formats的默认值为:

[ "strict_date_optional_time","yyyy/MM/dd HH:mm:ss Z||yyyy/MM/dd Z"]

Disabling date detection(禁用日期检测)

可以通过将date_detection设置为false来禁用动态日期检测:

PUT my_index
{
  "mappings": {
    "_doc": {
      "date_detection": false
    }
  }
}

PUT my_index/_doc/1 
{
  "create": "2015/09/02"
}

这个时候create字段就会是text字段。

Customising detected date formats(自定义检测到的日期格式)

可以通过自定义dynamic_date_formats来支持你自己的日期格式:

PUT my_index
{
  "mappings": {
    "_doc": {
      "dynamic_date_formats": ["MM/dd/yyyy"]
    }
  }
}

PUT my_index/_doc/1
{
  "create_date": "09/25/2015"
}

Numeric detection(数值检测)

虽然JSON支持原生的浮点型和整型数据类型,但是有些应用程序或语言有时会将数字作为字符串。通常正确的解决方案是显式的映射这些字段,但是可以启用数字检测(默认情况下是禁用的)来自动执行此操作。

PUT my_index
{
  "mappings": {
    "_doc": {
      "numeric_detection": true
    }
  }
}

PUT my_index/_doc/1
{
  "my_float":   "1.0", 
  "my_integer": "1" 
}

上面的my_float字段已添加为double类型字段,my_integer字段已添加为long类型字段

Dynamic templates(动态模板)

动态模板允许你定义可以用于动态添加的字段的自定义映射,匹配条件主要就是使用下面这几种参数:
1.可以利用Elasticsearch中的match_mapping_type去检测数据类型;
2.可以使用match(匹配)和unmatch(不匹配)或match_pattern(模式匹配)取匹配字段的名称;
3.使用path_match(路径匹配)和path_unmatch(不匹配路径)去匹配用.连接的全路径

原始字段名称{name}和检测到的数据类型{dynamic_type}模板变量可以在映射规范中用作占位符。
仅当字段包含具体值(不为空或空数组)时才添加动态字段映射。这意味着如果在dynamic_template中使用null_value选项,只能在该字段具有的具体值已被索引第一个文档之后才会应用该值。

什么是动态模版

动态模板是指定为命名对象的一个数组:

"dynamic_templates": [
    {
      "my_template_name": { //模版名称可以是任意字符串
        ...  match conditions ... 
        "mapping": { ... }  //最后要mapping的目标类型
      }
    },
    ...
  ]

匹配条件可以包括以下任何一种:match_mapping_type(匹配映射类型),match(匹配),match_pattern(模式匹配),unmatch(不匹配),path_match(路径匹配),path_unmatch(取消路径匹配)。
模版会按照顺序取处理,第一个匹配上的模版会赢(就是会用这个模版)。当通过put mapping的api添加新的动态模版时候,所有存在的模版都会被重写覆盖。这是考虑到模版添加后会被记录或者删除。

match_mapping_type

match_mapping_type利用json语法规则确定数据类型,JSON不能区分integer还是long,是float还是double,所以都会默认选更大的数据类型,默认是long和double。
下面这几种数据类型会自动探测到的:

碰到ture和false会变成boolean
当date detection开启并且string符合配置的日期格式
有小数部分是double
没有小数部分是long
objects是object
字符串是string
*可以匹配各种数据类型

例如,如果我们要将所有整数字段映射为integer(整型)而不是long(长整型),并且所有string(字符串类型)字段都是text(文本)和keyword(关键词),我们可以使用以下模板:

PUT my_index
{
  "mappings": {
    "_doc": {
      "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
                }
              }
            }
          }
        }
      ]
    }
  }
}

match and unmatch(匹配和不匹配)

match参数使用模式匹配字段名称,而unmatch使用模式排除match(匹配)的字段。
以下示例匹配名称为long_开头(以_text结尾的字段字符串除外)的所有string(字符串类型)字段,并将其映射为long(长整型)字段:

PUT my_index
{
  "mappings": {
    "_doc": {
      "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" 
}

match_pattern(正则表达式匹配)

match_pattern参数调整match参数的行为,使其在字段名称上支持匹配完整的Java正则表达式,而不是简单的通配符,例如:

"match_pattern": "regex",
"match": "^profit_\\d+$" //注意转义字符

path_match and path_unmatch(路径匹配和不匹配路径)

path_match和path_unmatch参数的工作方式与match和unmatch相同
下面的示例将name对象中的任何字段的值复制到顶级full_name字段,但middle字段除外:

PUT my_index
{
  "mappings": {
    "_doc": {
      "dynamic_templates": [
        {
          "full_name": {
            "path_match":   "name.*",
            "path_unmatch": "*.middle",
            "mapping": {
              "type":       "text",
              "copy_to":    "full_name"
            }
          }
        }
      ]
    }
  }
}

PUT my_index/_doc/1
{
  "name": {
    "first":  "Alice",
    "middle": "Mary",
    "last":   "White"
  }
}

{name} and {dynamic_type}占位符

在映射中{name}和{dynamic_type}占位符会被替换为字段名称和检测到的动态类型。以下示例将所有的字符串类型设置为使用与该字段名称相同的analyzer(分析器),并禁用所有非字符串字段的doc_values:

PUT my_index
{
  "mappings": {
    "_doc": {
      "dynamic_templates": [
        {
          "named_analyzers": {
            "match_mapping_type": "string",
            "match": "*",
            "mapping": {
              "type": "text",
              "analyzer": "{name}"
            }
          }
        },
        {
          "no_doc_values": {
            "match_mapping_type":"*",
            "mapping": {
              "type": "{dynamic_type}",
              "doc_values": false
            }
          }
        }
      ]
    }
  }
}

PUT my_index/_doc/1
{
  "english": "Some English text", 
  "count":   5 
}

当put文档的时候,"english": "Some English text"这个字段是string,第一个模版named_analyzers匹配成功,然后会把字段映射为text,分析器会变成这个字段的名字english(一定要有这个分析器),"count": 5 第一个模版没匹配上,第二个模版匹配上,类型就是自动动态映射的类型,这是个整数,那就变成long类型。

Template examples(动态模板示例)

下面是一些很有用的动态模板示例:

Structured search(结构化搜索)

默认情况下,elasticsearch将字符串字段映射为具有子keyword(关键字)字段的text(文本)字段。但是,如果你只想索引结构化内容,对全文检索不感兴趣,你可以使用elasticsearch将你的字段映射为“关键字”。

PUT my_index
{
  "mappings": {
    "_doc": {
      "dynamic_templates": [
        {
          "strings_as_keywords": {
            "match_mapping_type": "string",
            "mapping": {
              "type": "keyword"
            }
          }
        }
      ]
    }
  }
}

text-only mappings for strings(字符串的纯文字映射)

与上一个例子相反,如果你对这些字符串字段唯一在意的事情就是在这些字段上进行全文检索,并且如果你不打算在该字符串字段上运行聚合,排序或精确搜索,你可以告诉elasticsearch将它仅映射为文本字段(这是5.0之前的默认行为):

PUT my_index
{
  "mappings": {
    "_doc": {
      "dynamic_templates": [
        {
          "strings_as_text": {
            "match_mapping_type": "string",
            "mapping": {
              "type": "text"
            }
          }
        }
      ]
    }
  }
}

Disabled norms(禁用规范)

Norms(规范)是索引时评分的因子。如果你不关心评分,比如你不需要按分数排序文档的情况,你可以在索引中禁用这些评分因子的存储,这样能够节省一些空间。

PUT my_index
{
  "mappings": {
    "_doc": {
      "dynamic_templates": [
        {
          "strings_as_keywords": {
            "match_mapping_type": "string",
            "mapping": {
              "type": "text",
              "norms": false,
              "fields": {
                "keyword": {
                  "type": "keyword",
                  "ignore_above": 256
                }
              }
            }
          }
        }
      ]
    }
  }
}

Time-series(时间序列)

当使用elasticsearch进行时间序列分析,通常你会经常对这些数值字段进行聚合分析,而不是进行过滤查询。在这种情况下,你可以使用index参数禁用这些字段上的索引来节省磁盘空间,同时可能获得一些索引速度的提升:

PUT my_index
{
  "mappings": {
    "_doc": {
      "dynamic_templates": [
        {
          "unindexed_longs": {
            "match_mapping_type": "long",
            "mapping": {
              "type": "long",
              "index": false
            }
          }
        },
        {
          "unindexed_doubles": {
            "match_mapping_type": "double",
            "mapping": {
              "type": "float", 
              "index": false
            }
          }
        }
      ]
    }
  }
}

default mapping(6.0已经移除)

6.0以前多个type的时候,对于一个doc会有一个default mapping
现在一个type,就没有意义了

Although mapping is Over, Search is coming soon.

发表评论

电子邮件地址不会被公开。