Elasticsearch——动态映射

目录

Dynamic field mappings

date detection (日期检测)

Disabling date detection (禁用日期检测)

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

Numeric detection (数字检测)

Dynamic templates

验证动态模板

在动态模板映射运行时字段


Elasticsearch最重要的功能之一就是它会尽量避开我们的视线,让我们尽快开始探索我们的数据。要为文档编制索引,不必首先创建索引、定义映射类型和定义字段 — 我们只需为文档编制索引,索引、类型和字段将自动显示:

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

创建data索引、_doc映射类型和名为count且数据类型为long的字段。

自动检测和添加新字段称为动态映射。动态映射规则可以通过以下方式进行自定义以满足我们的目的:

Dynamic field mappings

    管理动态字段发现的规则。

    当Elasticsearch在文档中检测到一个新字段时,它会在默认情况下动态地将该字段添加到类型映射中。动态参数控制此行为。

    通过将动态参数设置为true或runtime,可以显式指示Elasticsearch基于传入文档动态创建字段。启用动态字段映射后,Elasticsearch使用下表中的规则来确定如何映射每个字段的数据类型。

下表中的字段数据类型是Elasticsearch动态检测的唯一字段数据类型。必须显式映射所有其他数据类型

JSON data type

"dynamic":"true"

"dynamic":"runtime"

null

No field added

No field added

true or false

boolean

boolean

double

float

double

integer

long

long

object1

object

object

array

Depends on the first non-null value in the array

Depends on the first non-null value in the array

string that passes date detection

date

date

string that passes numeric detection

float or long

double or long

string that doesn’t pass date detection or numeric detection

text with a .keyword sub-field

keyword

object始终映射为properties部分的一部分,即使动态参数设置为runtime。

我们可以在document和object级别禁用动态映射。将动态参数设置为false将忽略新字段,如果Elasticsearch遇到未知字段,strict将拒绝文档。

使用更新映射API更新现有字段的动态设置。

可以自定义用于日期检测和数字检测的动态字段映射规则。要定义可应用于其他动态字段的自定义映射规则,请使用动态模板(dynamic templates)。

date detection (日期检测)

如果启用了日期检测(默认),则会检查新的字符串字段,以查看其内容是否与dynamic_date_formats中指定的任何日期模式匹配。如果找到匹配项,则会使用相应的格式添加一个新的日期字段。

dynamic_date_formats 默认值是:

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

例如:

PUT my-index-000001/_doc/1
{
  "create_date": "2015/09/02"
}

GET my-index-000001/_mapping 

create_date字段被做为date类型字段增加,格式为:"yyyy/MM/dd HH:mm:ss Z||yyyy/MM/dd Z".

Disabling date detection (禁用日期检测)

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

PUT my-index-000001
{
  "mappings": {
    "date_detection": false
  }
}

PUT my-index-000001/_doc/1 
{
  "create": "2015/09/02"
}

这个create 字段会被做为text类型字段增加。

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

或者,dynamic_date_formats可以被定制,以支持我们自己的日期格式:

PUT my-index-111
{
  "mappings": {
    "dynamic_date_formats": ["MM/dd/yyyy"]
  }
}

PUT my-index-111/_doc/1
{
  "create_date": "09/25/2015"
}

Numeric detection (数字检测)

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

PUT my-index-000001
{
  "mappings": {
    "numeric_detection": true
  }
}

PUT my-index-000001/_doc/1
{
  "my_float":   "1.0", 
  "my_integer": "1" 
}

my_float字段 作为float类型增加。

my_integer字段作为long类型增加。

Dynamic templates

    为动态添加的字段配置映射的自定义规则。

索引模板允许我们为新索引配置默认映射、设置和别名,无论是自动创建的还是显式创建的。

动态模板允许我们更好地控制Elasticsearch如何映射数据,而不是默认的动态字段映射规则。通过将动态参数设置为true或runtime,可以启用动态映射。然后,可以使用动态模板定义自定义映射,这些映射可以基于匹配条件应用于动态添加的字段:

  • match_mapping_type 对Elasticsearch检测到的数据类型进行操作。
  • match and unmatch 在字段名上使用模式进行匹配。
  • path_match and path_unmatch 在字段的完整虚线路径上操作。

  • 如果动态模板没有定义匹配类型、匹配或路径匹配,则它不会匹配任何字段。我们仍然可以在批量请求的动态模板部分按名称引用模板。

使用映射规范中的{name}和{dynamic_type}模板变量作为占位符。

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

"dynamic_templates": [
    {
      "my_template_name": { (1)
        ... match conditions ... (2)
        "mapping": { ... }  (3)
      }
    },
    ...
  ]

1、模板名称可以是任何字符串值。

2、匹配条件可以包括:匹配映射类型(match_mapping_type)、匹配(match)、匹配模式(match_pattern)、不匹配(unmatch)、路径匹配(path_match)、路径不匹配(path_unmatch)。

3、匹配字段应使用的映射。

验证动态模板

如果提供的映射包含无效的映射片段,则返回验证错误。在索引时应用动态模板时,以及在大多数情况下更新动态模板时,会发生验证。在某些情况下,提供无效的映射片段可能会导致动态模板的更新或验证失败:

  • 如果未指定匹配的映射类型,但模板对至少一个预定义的映射类型有效,则认为映射段有效。但是,如果与模板匹配的字段被索引为不同类型,则在索引时会返回验证错误。例如,将动态模板配置为不匹配映射类型(no match_mapping_type )被视为有效的字符串类型,但如果将与动态模板匹配的字段索引为long,则会在索引时返回验证错误。建议将match_mapping_type配置为预期的JSON类型,或在映射片段中配置所需的类型。
  • 如果在映射片段中使用了{name}占位符,则更新动态模板时将跳过验证。这是因为当时字段名未知。相反,在索引时应用模板时会进行验证。

模板按顺序处理 — 第一个匹配的模板获胜。通过更新映射API放置新的动态模板时,将覆盖所有现有模板。这允许动态模板在最初添加后重新排序或删除。

在动态模板映射运行时字段

如果希望Elasticsearch将特定类型的新字段动态映射为运行时字段,请在索引映射中设置“dynamic”:“runtime”。这些字段没有索引,在查询时从_source加载。

或者,可以使用默认的动态映射规则,然后创建动态模板,将特定字段映射为运行时字段。在索引映射中设置“dynamic”:“true”,然后创建一个动态模板,将某个类型的新字段映射为运行时字段。

假设我们有数据,其中每个字段都以ip_开头。基于动态映射规则,Elasticsearch将任何通过数字检测的字符串映射为float或long。但是,可以创建一个动态模板,将新字符串映射为ip类型的运行时字段。

下面的请求定义了一个名为strings_as_ip的动态模板。当Elasticsearch检测到与ip*模式匹配的新字符串字段时,它会将这些字段映射为ip类型的运行时字段。因为ip字段不是动态映射的,所以可以将此模板与“dynamic”:“true”或“dynamic”:“runtime”一起使用。

PUT my-index-000001/
{
  "mappings": {
    "dynamic_templates": [
      {
        "strings_as_ip": {
          "match_mapping_type": "string",
          "match": "ip*",
          "runtime": {
            "type": "ip"
          }
        }
      }
    ]
  }
}

match_mapping_type:

匹配映射类型(match_mapping_type)是JSON解析器检测到的数据类型。因为JSON不区分long和整数,也不区分double和float,所以它总是选择更广泛的数据类型,比如long代表整数,double代表浮点数。

Elasticsearch自动检测以下数据类型:

JSON data type

"dynamic":"true"

"dynamic":"runtime"

null

No field added

No field added

true or false

boolean

boolean

double

float

double

integer

long

long

object1

object

object

array

Depends on the first non-null value in the array

Depends on the first non-null value in the array

string that passes date detection

date

date

string that passes numeric detection

float or long

double or long

string that doesn’t pass date detection or numeric detection

text with a .keyword sub-field

keyword

objects 始终映射为属性部分的一部分,即使动态参数设置为运行时也是如此。

使用通配符(*)匹配所有数据类型。

例如,如果要将所有整型字段映射为整数而不是长型,将所有字符串字段映射为文本和关键字,则可以使用以下模板:

PUT my-index-000001
{
  "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-000001/_doc/1
{
  "my_integer": 5, (1)
  "my_string": "Some string"  (2)
}

1、my_integer 字段被映射为 integer类型。

2、my_string 字段被映射为text,带有一个 keyword multi field

match and unmatch:

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

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

 "match_pattern": "regex",
  "match": "^profit_\d+$"

以下示例匹配名称以long_开头的所有字符串字段(以_text结尾的字段除外),并将其映射为long字段:

PUT my-index-000001
{
  "mappings": {
    "dynamic_templates": [
      {
        "longs_as_strings": {
          "match_mapping_type": "string",
          "match":   "long_*",
          "unmatch": "*_text",
          "mapping": {
            "type": "long"
          }
        }
      }
    ]
  }
}

PUT my-index-000001/_doc/1
{
  "long_num": "5", (1)
  "long_text": "foo" (2)
}

1、long_num 被映射为 long

2、long_text 使用默认的string映射

path_match and path_unmatch:

path_match和path_unmatch参数的工作方式与match和unmatch相同,但操作方式是指向字段的完整虚线路径,而不仅仅是最终名称,例如some_object.*.some_field。

此示例将名称对象中任何字段的值复制到顶级full_name字段,middle字段除外:

PUT my-index-000001
{
  "mappings": {
    "dynamic_templates": [
      {
        "full_name": {
          "path_match":   "name.*",
          "path_unmatch": "*.middle",
          "mapping": {
            "type":       "text",
            "copy_to":    "full_name"
          }
        }
      }
    ]
  }
}

PUT my-index-000001/_doc/1
{
  "name": {
    "first":  "John",
    "middle": "Winston",
    "last":   "Lennon"
  }
}

请注意,除了leaf 字段之外,path_match和path_unmatch参数在对象路径上也匹配。例如,为以下文档编制索引将导致错误,因为“路径匹配”设置还与对象字段name.title匹配,该字段不能映射为文本:

PUT my-index-000001/_doc/2
{
  "name": {
    "first":  "Paul",
    "last":   "McCartney",
    "title": {
      "value": "Sir",
      "category": "order of chivalry"
    }
  }
}

Template variables

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

PUT my-index-000001
{
  "mappings": {
    "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-000001/_doc/1
{
  "english": "Some English text",  (1)
  "count":   5  (2)
}

1、英语字段被映射为英语分析器的字符串字段。

2、count 字段映射long字段在禁用doc_values的时候。

动态模板例子:

以下是一些可能有用的动态模板示例:

 结构化搜索:

设置“dynamic”:“true”时,Elasticsearch将字符串字段映射为带有关键字子字段的文本字段。如果我们只为结构化内容编制索引,而对全文搜索不感兴趣,则可以使Elasticsearch仅将字段映射为关键字字段。但是,我们必须搜索与搜索这些字段所索引的值完全相同的值。

PUT my-index-000001
{
  "mappings": {
    "dynamic_templates": [
      {
        "strings_as_keywords": {
          "match_mapping_type": "string",
          "mapping": {
            "type": "keyword"
          }
        }
      }
    ]
  }
}

字符串的纯文本映射:

与上一个示例相反,如果我们只关心字符串字段的全文搜索,而不打算运行聚合、排序或精确搜索,则可以指示Elasticsearch将字符串映射为文本:

PUT my-index-000001
{
  "mappings": {
    "dynamic_templates": [
      {
        "strings_as_text": {
          "match_mapping_type": "string",
          "mapping": {
            "type": "text"
          }
        }
      }
    ]
  }
}

或者,我们可以创建动态模板,将字符串字段映射为映射的运行时部分中的keyword字段。当Elasticsearch检测到string类型的新字段时,这些字段将创建为keyword类型的运行时字段。

虽然我们的string字段不会被编入索引,但它们的值存储在_source中,可以用于搜索请求、聚合、筛选和排序。

例如,以下请求创建一个动态模板,将string字段映射为keyword类型的运行时字段。虽然运行时定义为空,但新srting 字段被映射为keyword运行时字段是基于动态映射规则让Elasticsearch使用新增字段类型去映射。任何未通过日期检测或数字检测的字符串将自动映射为keyword:

PUT my-index-000001
{
  "mappings": {
    "dynamic_templates": [
      {
        "strings_as_keywords": {
          "match_mapping_type": "string",
          "runtime": {}
        }
      }
    ]
  }
}

索引一个简单的文档:

PUT my-index-000001/_doc/1
{
  "english": "Some English text",
  "count":   5
}

查看映射时,我们将看到english字段是一个运行时字段,其类型为关键字:

GET my-index-000001/_mapping
{
  "my-index-000001" : {
    "mappings" : {
      "dynamic_templates" : [
        {
          "strings_as_keywords" : {
            "match_mapping_type" : "string",
            "runtime" : { }
          }
        }
      ],
      "runtime" : {
        "english" : {
          "type" : "keyword"
        }
      },
      "properties" : {
        "count" : {
          "type" : "long"
        }
      }
    }
  }
}

关闭norms:

norms 是指数时间评分因子。如果我们不关心评分(例如,如果我们从不按评分对文档排序),则可以禁用索引中这些评分因子的存储并节省一些空间。

PUT my-index-000001
{
  "mappings": {
    "dynamic_templates": [
      {
        "strings_as_keywords": {
          "match_mapping_type": "string",
          "mapping": {
            "type": "text",
            "norms": false,
            "fields": {
              "keyword": {
                "type": "keyword",
                "ignore_above": 256
              }
            }
          }
        }
      }
    ]
  }
}

此模板中显示的子关键字字段与动态映射的默认规则一致。当然,如果我们不需要它们,因为我们不需要在此字段上执行精确的搜索或聚合,可以按照上一节中的描述将其删除。

时间序列(Time series)

在使用Elasticsearch进行时间序列分析时,通常会有许多数字字段,我们通常会对这些字段进行聚合,但从不进行筛选。在这种情况下,我们可以禁用对这些字段的索引以节省磁盘空间,还可以获得一些索引速度:

PUT my-index-000001
{
  "mappings": {
    "dynamic_templates": [
      {
        "unindexed_longs": {
          "match_mapping_type": "long",
          "mapping": {
            "type": "long",
            "index": false
          }
        }
      },
      {
        "unindexed_doubles": {
          "match_mapping_type": "double",
          "mapping": {
            "type": "float", (1)
            "index": false
          }
        }
      }
    ]
  }
}

1、与默认的动态映射规则一样,double映射为float,这通常足够精确,但需要一半的磁盘空间。

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值