关于后端:Elasticsearch进阶使用动态模版

42次阅读

共计 9589 个字符,预计需要花费 24 分钟才能阅读完成。

总进度

Elasticsearch 8.1 认证工程师学习路线

明天咱们来学习 Elasticsearch 中的动静模版,其实咱们在第一课 2.2.3 章节中就曾经学过了相似的了,链接如下

依据给定的需要创立索引

然而明天咱们学点不一样的,上次只是简略的应用,这次咱要深刻了解,完满掌控才是第一指标,废话少说,上面开始

什么是动静模版

动静模版容许咱们管制动静字段映射规定之外的数据

动静字段的映射咱们能够设置 dynamic 参数为 true 或者 runtime 来启用动静映射,也能够自定义动静映射模版自定义映射,自定义之后的模版就能够依据匹配规定利用于动静增加的字段。在上一节中,动静映射规定曾经说过,本节间接搬过去,如下

JSON data type "dynamic":"true" "dynamic":"runtime"
null 不增加 不增加
true or false boolean boolean
double float double
long long long
object object 不增加
array 依据数组中第一个非空的值判断 依据数组中第一个非空的值判断
日期类型的字符串 date date
数字类型的字符串 float or long double or long
不是日期也不是数字的字符串 text类型以及 .keyword 的字类型 keyword

其中自定义动静模版匹配规定形式有如下

  • match_mapping_typeElasticsearch 中检测到的数据类型进行操作,参考上方图表
  • matchunmatch 能够应用模式匹配字段名
  • path_matchpath_unmatch 对字段的残缺虚线门路进行操作
  • 如果动静模版没有定义 march_mapping_typematchpath_match,那么模版不会匹配任何一个字段。然而 _bulk 申请时能够通过模版名援用模版

也能够应用 {name}{dynamic_type}模版变量作为占位符,比方后文中应用占位符实现分词器的指定等

动静模版的定义是对象数组

"dynamic_templates":[
  {
    "my_template_name":{#1
      ... 匹配条件 ...#2
      "mapping":{...}#3
    }
  },
  ...
]
  1. 自定义模版名称,能够是任意的字符串
  2. 模版的应用匹配条件能够是:match_mapping_type,match,match_pattern,unmatch,path_match,path_unmatch
  3. 匹配字段应该应用的索引映射

通过下面的 学习,咱们晓得了动静模版的定义,既然定义好了就该有验证,毕竟定义好的模版能不能用,是否定义的正确性还是须要验证的

验证动静模版

如果定义的模版蕴含有效的映射片段则会返回谬误。在 index 操作时利用动静模版进行验证,然而大多数状况下在动静模版更新的时候会进行验证。提供有效的映射片段可能造成在更新或者某些条件下动静模版的验证失败,比方:

  • 如果没有指定 match_mapping_type,然而这个模版提供了起码一个的无效映射,那么这个映射片段是无效的。然而如果将与模版匹配的字段映射为其余类型,则在 index 时返回验证谬误。例如:配置一个动静模版,不蕴含match_mapping_type,这样就是一个无效的字符串类型,然而如果有一个字段匹配动静模版时被匹配为long,那么在index 时将返回验证谬误。倡议就是将 match_mapping_type 配置为预期的 JSON 类型(参考结尾的映射关系表)或者在 mapping 中配置好所需的类型
  • 如果咱们在 mapping 的片段中应用了 {name} 占位符,那么在动静模版的更新时是跳过验证的。这是因为过后的字段名还是不晓得的,所以在 index 时进行验证

如果有多个模版同时匹配,依照程序匹配规定解决,第一个匹配的模版具备最高的优先级;当通过 update mapping API 更新动静模版时,所有的现有模版将会被笼罩,这就容许在最后的创立动静模版之后能够从新排序或者删除它们

动静模版中映射运行时字段

在上一节中咱们的本大节内容例子就是应用的这个,有趣味的能够回过头再看一眼,链接放到文章结尾了

如果咱们想 Elasticsearch 将某一种类型的新字段动静映射为运行时字段,那么咱们能够通过设置 "dynamic":"runtime", 这些字段不会被编入索引,并且在查问时是从_source 加载

或者咱们应用默认的动静映射规定,而后创立动静模版,并将特定的字段映射为运行时字段。咱们须要在 index mapping 中设置 "dynamic:"true", 而后创立一个动静模版,并将某种类型的新字段映射为运行时字段

举个例子,假如咱们有一组数据,其中每个字段都是 _ip 结尾的,依据动静映射规定,Elasticsearch会依据数值检测到的任何的字符串映射为 float 或者 long,此时咱们就能够创立一个动静模版,将这个新字符串映射为ip 类型的运行时字段

上面是咱们的一个例子,大略意思就是当 Elasticsearch 应用匹配模式是 ip* 的新字段时,它会将这些字段映射为 ip 类型的运行时字段。因为这些字段不是动静映射的,所以咱们能够应用 "dynamic":"true" 或者 "dynamic":"runtime" 联合应用

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

联合 "dynamic":"true" 或者 "dynamic":"runtime" 应用

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

下面的语句,咱们会把合乎匹配模式 ip* 的新字段映射为运行时字段,然而因为咱们设置 "dynamic":"runtime", 所以前面的新字段咱们都会设置为运行时字段,也就是上面这个语句,其中ip_req,ip_res, 合乎动静模版dynamic_templates 的匹配规定 ip*,而my_ip 应用索引结尾设置的 "dynamic":"runtime" 也会退出到运行时字段

PUT my-dynamic-template-001/_doc/1
{
  "ip_req":"127.0.0.1",
  "ip_res":"127.0.0.1",
  "my_ip":"locahost"
}

此时咱们查看索引状况如下

{
  "my-dynamic-template-001" : {
    "mappings" : {
      "dynamic" : "runtime",
      "dynamic_templates" : [
        {
          "strings_as_ip" : {
            "match" : "ip*",
            "match_mapping_type" : "string",
            "runtime" : {"type" : "ip"}
          }
        }
      ],
      "runtime" : {
        "ip_req" : {"type" : "ip"},
        "ip_res" : {"type" : "ip"},
        "my_ip" : {"type" : "keyword"}
      }
    }
  }
}

下面就是一个简略的应用,其中

  • match_mapping_typestring,也就是字段的值是字符串
  • matchip* 即该字段名为ip 结尾的
  • runtime 定义被映射的字段类型,在下面例子中,被映射为runtime,类型为ip

match_mapping_type

match_mapping_typeJSON 解析器检测到的数据类型。因为 JSON 不辨别 longinteger,也不辨别 doublefloat,所以解析时 doublefloat都会被认为是 doubleintegerlong都会被认为是long

留神:当应用动静映射的时候,ELasticsearch 将始终抉择更宽泛的数据类型,然而有个例外是 float 类型,它的须要的存储空间少于 double,并且对于大多数的应用程序来说足够精确。然而运行时字段不反对float 类型,所以这就是 "dynamic":"runtime" 应用 double 的起因

Elasticsearch 会自动检测数据类型,检测规定就是文章结尾的那个表格内容,并且咱们还能够应用 match_mapping_type 中应用通配符 * 来匹配所有的数据类型

举个例子,如果咱们想把整数字段映射为 integer 而不是 long 类型,字符串字段匹配为 textkeyword类型,咱们能够应用如下模版

  • 创立一个模版
PUT my-dynamic-template-002
{
  "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-dynamic-template-002/_doc/1
    {
      "my_integer": 5, 
      "my_string": "Some string" 
    }
  • 查看生成的mapping

    GET my-dynamic-template-002/_mapping

    返回后果如下,my_integer会被映射为 integermy_string 会被映射为 textkeyword

    {
      "my-dynamic-template-002" : {
        "mappings" : {
          "dynamic_templates" : [
            {
              "integers" : {
                "match_mapping_type" : "long",
                "mapping" : {"type" : "integer"}
              }
            },
            {
              "strings" : {
                "match_mapping_type" : "string",
                "mapping" : {
                  "fields" : {
                    "raw" : {
                      "ignore_above" : 256,
                      "type" : "keyword"
                    }
                  },
                  "type" : "text"
                }
              }
            }
          ],
          "properties" : {
            "my_integer" : {"type" : "integer"},
            "my_string" : {
              "type" : "text",
              "fields" : {
                "raw" : {
                  "type" : "keyword",
                  "ignore_above" : 256
                }
              }
            }
          }
        }
      }
    }
    

match 与 unmatch

match 应用模式匹配字段名称,unmatch 应用模式排除匹配字段

match_pattern能够通过设置此参数值调整 match 参数的行为,使 match 参数反对与字段名匹配的残缺 Java 正则表达式来代替简略的通配符,如下

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

如下示例,咱们匹配名称以 long_ 结尾的所有字符串字段,排出以 _text 结尾的字符串字段,并将它们映射为 long 类型的字段


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

PUT my-dynamic-template-003/_doc/1
{
  "long_num": "5", 
  "long_text": "foo" 
}

GET my-dynamic-template-003/_mapping

在下面例子中,long_num被映射为 long 类型的字段,这是因为 match_mapping_typestring类型,并且是 long_ 结尾的。long_text尽管是 long_ 结尾的,然而也是 _text 结尾的,合乎 unmatch 条件,这样的话 long_text 就依照默认规定 string 进行映射,生成 textkeyword字段

path_match 与 path_unmatch

path_matchpath_unmatchmatchunmatch 原理相似,然而是对字段的残缺虚线门路进行匹配,而不仅仅是最终名称,例如some_object.*.some_field

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

PUT my-dynamic-template-004/_doc/1
{
  "name": {
    "first":  "John",
    "middle": "Winston",
    "last":   "Lennon"
  }
}

如上所示,但凡 name 下的任何字段,除了以 middle 结尾的字段除外,都会被映射为 text 类型,并且 copy_to 带有full_name

执行如下命令查看

GET my-dynamic-template-004/_mapping

显示后果如下

{
  "my-dynamic-template-004" : {
    "mappings" : {
      "dynamic_templates" : [
        {
          "full_name" : {
            "path_match" : "name.*",
            "path_unmatch" : "*.middle",
            "mapping" : {
              "copy_to" : "full_name",
              "type" : "text"
            }
          }
        }
      ],
      "properties" : {
        "full_name" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        },
        "name" : {
          "properties" : {
            "first" : {
              "type" : "text",
              "copy_to" : ["full_name"]
            },
            "last" : {
              "type" : "text",
              "copy_to" : ["full_name"]
            },
            "middle" : {
              "type" : "text",
              "fields" : {
                "keyword" : {
                  "type" : "keyword",
                  "ignore_above" : 256
                }
              }
            }
          }
        }
      }
    }
  }
}

从下面的后果可知,咱们可能看进去,name之下的 middle 没有 copy_to,它的映射依照默认的string 映射规定,生成 text 以及keyword

须要留神的是,除了 leaf 字段外,path_matchpath_unmatch 参数匹配对象门路,如下对文档索引将产生谬误,因为 name.title 不能映射为文本类型

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

报错如下

{
  "error" : {
    "root_cause" : [
      {
        "type" : "mapper_parsing_exception",
        "reason" : "failed to parse field [name.title] of type  in document with id'2'. Preview of field's value: '{category=order of chivalry, value=Sir}'"
      }
    ],
    "type" : "mapper_parsing_exception",
    "reason" : "failed to parse field [name.title] of type  in document with id'2'. Preview of field's value: '{category=order of chivalry, value=Sir}'",
    "caused_by" : {
      "type" : "illegal_state_exception",
      "reason" : "Can't get text on a START_OBJECT at 5:14"
    }
  },
  "status" : 400
}

template variables(模版变量)

{name}{dynamic_type} 占位符在映射中被替换为字段名称和检测到的动静类型

如下示例,将所有的字符串字段应用与字段同名的分析器,并禁用所有不是字符串字段的doc_values


PUT my-dynamic-template-005
{
  "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-dynamic-template-005/_doc/1
{
  "english": "Some English text", 
  "count":   5 
}
GET my-dynamic-template-005/_mapping

在下面例子中,{name} 被替换为 field name,而{dynamic_type} 被替换为有 JSON 解析器检测到的数据类型

english字段分析器设置为 english,而count 被检测为 long 类型,并且 doc_values 设置为false

动静模版的例子

结构化搜寻

当咱们设置 "dynamic":"true" 时,Elasticsearch 会将字符串字段映射为 text 类型,并带有一个 keyword 类型的子字段,如果咱们只是结构化的搜寻,对全文检索不须要,那么咱们就能够让 Elasticsearch 映射为 keyword 字段,然而这样做的话,必须搜寻与索引完全相同的值能力搜寻这些字段,也就是准确匹配

PUT my-dynamic-template-006
{
  "mappings": {
    "dynamic_templates": [
      {
        "strings_as_keywords": {
          "match_mapping_type": "string",
          "mapping": {"type": "keyword"}
        }
      }
    ]
  }
}

字符串的纯文本映射

与下面结构化搜寻相同,如果咱们只关怀全文检索,并且不会对字段进行聚合、排序和准确查找,那么咱们让 Elasticsearch 将字符串映射为 text 类型

PUT my-dynamic-template-007
{
  "mappings": {
    "dynamic_templates": [
      {
        "strings_as_text": {
          "match_mapping_type": "string",
          "mapping": {"type": "text"}
        }
      }
    ]
  }
}

对于最近版本减少的运行时字段,咱们呢还能够创立一个动静模版,将字符串映射为运行时的 keyword 类型,虽说该字段不会被索引,然而它们的值是存在 _source 中,并且能够用于搜寻、聚合、过滤和排序

例如如下示例,将创立一个动静模版,将 string 字段映射为 keyword 运行时字段,尽管 runtime 定义是空的,然而 Elasticsearch 会应用文章结尾的匹配规定增加,任何一个未通过工夫或者数字检测的字符串都会被映射为 keyword 类型

PUT my-dynamic-template-008
{
  "mappings": {
    "dynamic_templates": [
      {
        "strings_as_keywords": {
          "match_mapping_type": "string",
          "runtime": {}}
      }
    ]
  }
}

此时咱们索引一个文档

PUT my-dynamic-template-008/_doc/1
{
  "english": "Some English text",
  "count":   5
}

查看映射关系时,能够看到 english 被映射为 keyword 类型的运行时字段

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

Disable norms

如果咱们不依照评分进行排序,那么能够禁用索引中的评分因子以节俭空间

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

下面模版中呈现的 keyword 的关键字字段是与动静映射的默认规定统一的,如果咱们不须要能够依照下面的例子将其删除

工夫序列

在应用 Elasticsearch 进行工夫序列的剖析时,通常会有很多的数字字段,然而这些数字字段个别不会进行过滤通常都是进行聚合。在这种状况下咱们能够禁用这些字段的索引以节俭磁盘空间,或者也可能取得一些索引的速度

PUT my-dynamic-template-010
{
  "mappings": {
    "dynamic_templates": [
      {
        "unindexed_longs": {
          "match_mapping_type": "long",
          "mapping": {
            "type": "long",
            "index": false
          }
        }
      },
      {
        "unindexed_doubles": {
          "match_mapping_type": "double",
          "mapping": {
            "type": "float", 
            "index": false
          }
        }
      }
    ]
  }
}

与默认的动静规定一样,double被映射为float,因为他能够满足绝大多数的申请。并且只须要一半的磁盘空间

总结

好了对于动静模版的常识到这就完结了,从开始介绍什么是动静模版,其次是动静模版如何应用以及最初的动静模版的罕用示例,那么你把握了多少呢,快去尝试一下吧,下一篇预报《为工夫序列索引定义索引生命周期策略 ILM》敬请期待

本文由 mdnice 多平台公布

正文完
 0