IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    [译]Elasticsearch - 自动检测及动态映射Dynamic Mapping

    xifeijian发表于 2016-04-07 23:34:34
    love 0

    一、自动映射:

    ES通过查看定义某文档的json格式就能猜测到文档结构,我们称之为自动映射,在开发过程中需要注意这些特性。

    字段自动检测

    在某个字段第一次出现时,如果之前没有定义过映射,ES会自动检测它可能满足的类型,然后创建对应的映射。

    JSON数据

    ES中的数据类型

    null

    不会添加字段

    true or false

    boolean

    floating point number

    double

    integer

    long

    object

    object

    array

    依赖于第一个非null得值

    string

    如果通过了date检测,则为date

    如果通过了numeric检测,则为Number

    上面就是类型自动检测的结果,除了上面列出的基本类型,其他的高级的类型比如geo,ip就需要手动指定了。

    日期自动检测

    日期自动检测,即date_detection是默认开启的,因此只要符合默认的日期格式,就可以自动创建成date类型

    日期的格式为:

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

    例如:

    复制代码
    $ curl -XPUT localhost:9200/test/test/1 -d '{"create":"2015/11/11"}'
    {"_index":"test","_type":"test","_id":"1","_version":1,"created":true}
    
    $ curl -XGET localhost:9200/test/_mapping?pretty
    {
      "test" : {
        "mappings" : {
          "test" : {
            "properties" : {
              "create" : {
                "type" : "date",
                "format" : "yyyy/MM/dd HH:mm:ss||yyyy/MM/dd"
              }
            }
          }
        }
      }
    }
    复制代码

    可以通过修改dynamic_date_formats 修改日期格式:

    复制代码
    PUT my_index
    {
        "mappings":{
            “my_type":{"dynamic_date_formats":["MM/dd/yyyy"]}
        }
    }
    
    PUT my_index/my_type/1{"create_date":"09/25/2015"}
    复制代码

    数字自动检测

    数字自动检测,即numeric_detection默认是关闭的。因此需要手动打开:

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

    当执行索引操作时,如果符合float型,就会自动创建为double,如果符合int型,ES默认创建为long

    可能通过类似curl -XPUT localhost:9200/test1/test1/_mapping?pretty查询自动生成的映射。

    二、动态映射:

    ES中有一个非常重要的特性——动态映射,即索引文档前不需要创建索引、类型等信息,在索引的同时会自动完成索引、类型、映射的创建。那么什么是映射呢?映射就是描述字段的类型、如何进行分析、如何进行索引等内容。

    当ES在文档中碰到一个以前没见过的字段时,它会利用动态映射来决定该字段的类型,并自动地对该字段添加映射。

    有时这正是需要的行为,但有时不是,需要留意。你或许不知道在以后你的文档中会添加哪些字段,但是你想要它们能够被自动地索引。或许你只是想要忽略它们。或者,尤其当你将ES当做主要的数据存储使用时,大概你会希望这些未知的字段会抛出异常来提醒你注意这一问题。

    幸运的是,你可以通过dynamic设置来控制这一行为,它能够接受以下的选项:

    • true:默认值。动态添加字段
    • false:忽略新字段
    • strict:如果碰到陌生字段,抛出异常

    dynamic设置可以适用在根对象上或者object类型的任意字段上。你应该默认地将dynamic设置为strict,但是为某个特定的内部对象启用它:

    PUT /my_index
    {
        "mappings": {
            "my_type": {
                "dynamic":      "strict", 
                "properties": {
                    "title":  { "type": "string"},
                    "stash":  {
                        "type":     "object",
                        "dynamic":  true 
                    }
                }
            }
        }
    }

    在my_type对象上如果碰到了未知字段则会抛出一个异常。 在stash对象上会动态添加新字段。

    通过以上的映射,你可以向stash添加新的可搜索的字段:

    PUT /my_index/my_type/1
    {
      "title": "This doc adds a new field",
      "stash": {
        "new_field": "Success!"
      }
    }

    但是,如果在顶层对象上试图添加新字段则会失败:

    PUT /my_index/my_type/1
    {
        "title":     "This throws a StrictDynamicMappingException",
        "new_field": "Fail!"
    }

    NOTE

    将dynamic设置为false并不会改变_source字段的内容,_source字段仍然会保存你索引的整个JSON文档。只不过是陌生的字段将不会被添加到映射中,以至于它不能被搜索到。


    自定义动态映射

    如果你知道你需要动态的添加的新字段,那么你也许会启用动态映射。然而有时动态映射的规则又有些不够灵活。幸运的是,你可以调整某些设置来让动态映射的规则更加适合你的数据。

    date_detection

    当ES碰到一个新的字符串字段时,它会检查该字串是否含有一个可被识别的日期,比如2014-01-01。如果存在,那么它会被识别为一个date类型的字段。否则会将它作为string进行添加。

    有时这种行为会导致一些问题。如果你想要索引一份这样的文档:

    { "note": "2014-01-01" }

    假设这是note字段第一次被发现,那么根据规则它会被作为date字段添加。但是如果下一份文档是这样的:

    { "note": "Logged out" }

    这时该字段显然不是日期,但是已经太迟了。该字段的类型已经是日期类型的字段了,因此这会导致一个异常被抛出。

    可以通过在根对象上将date_detection设置为false来关闭日期检测:

    PUT /my_index
    {
        "mappings": {
            "my_type": {
                "date_detection": false
            }
        }
    }

    有了以上的映射,一个字符串总是会被当做string类型。如果你需要一个date字段,你需要手动地添加它。

    NOTE

    ES中识别日期的方法可以通过dynamic_date_formats设置改变。

    dynamic_templates

    通过dynamic_templates,你可以拥有对新字段的动态映射规则拥有完全的控制。你设置可以根据字段名称或者类型来使用一个不同的映射规则。

    每个模板都有一个名字,可以用来描述这个模板做了什么。同时它有一个mapping用来指定具体的映射信息,和至少一个参数(比如match)用来规定对于什么字段需要使用该模板。

    模板的匹配是有顺序的 - 第一个匹配的模板会被使用。比如我们可以为string字段指定两个模板:

    • es:以_es结尾的字段名应该使用spanish解析器
    • en:其它所有字段使用english解析器

    我们需要将es模板放在第一个,因为它相比能够匹配所有字符串字段的en模板更加具体:

    PUT /my_index
    {
        "mappings": {
            "my_type": {
                "dynamic_templates": [
                    { "es": {
                          "match":              "*_es", 
                          "match_mapping_type": "string",
                          "mapping": {
                              "type":           "string",
                              "analyzer":       "spanish"
                          }
                    }},
                    { "en": {
                          "match":              "*", 
                          "match_mapping_type": "string",
                          "mapping": {
                              "type":           "string",
                              "analyzer":       "english"
                          }
                    }}
                ]
    }}}

    match_mapping_type允许你只对特定类型的字段使用模板,正如标准动态映射规则那样,比如string,long等。

    match参数只会匹配字段名,path_match参数用于匹配对象中字段的完整路径,比如address.*.name可以匹配如下字段:

    {
        "address":
            "city":
                "name": "New York"
            }
        }
    }

    unmatch和path_unmatch模式能够用来排除某些字段,没有被排除的字段则会被匹配。

    参考官方文档:https://www.elastic.co/guide/en/elasticsearch/reference/1.4//mapping-root-object-type.html





沪ICP备19023445号-2号
友情链接