Elasticsearch之深入映射。

根对象

映射的最高一层被称为根对象,它可能包含下面几项:

  • 一个properties节点,列出了文档中可能包含的每个字段的映射。
  • 多个元数据字段,每一个都以下划线开头,例如_type,_id和_source。
  • 设置项,控制如何动态处理新的字段,例如analyzer,dynamic_date_formats和dynamic_templates。
  • 其他设置,可以同时应用在根对象和其他object类型的字段上,例如enabled,dynamic和include_in_all。

属性

  • type:字段的数据类型,例如string 和 date。
  • index:字段是否应当被当成全文来搜索(analyzed),或被当成一个准确的值(not_analyzed),还是完全不可被搜索(no)。
  • analyzer:确定在索引或搜索时全文字段使用的分析器。

元数据:_source字段

默认情况下,Elasticsearch用JSON字符串来表示文档主体保存在_source字段中。像其他保存的字段一样,_source字段也会在写入硬盘前压缩。
这几乎始终是需要的功能,因为:
  • 搜索结果中能得到完整的文档——不需要额外去别的数据源中查询文档
  • 如果缺少_source字段,部分更新请求不会起作用
  • 当你的映射有变化,而且你需要重新索引数据时,你可以直接在Elasticsearch中操作而不需要重新从别的数据源中取回数据。
  • 你可以从_source中通过get或search请求取回部分字段,而不是整个文档。
  • 这样更容易排查错误,因为你可以准确的看到每个文档中包含的内容,而不是只能从一堆ID中猜测他们的内容。
即便如此,存储_source字段还是要占用硬盘空间的。假如上面的理由对你来说不重要,你可以用下面的映射禁用_source字段:
PUT /my_index
{
"mappings" : {
"my_type" : {
"_source" : {
"enabled" : false
}
}
}
}
在搜索请求中你可以通过限定_source字段来请求指定字段:
GET /_search
{
"query" : { "match_all" : {} },
"_source" : [ "title" , "created" ]
}
这些字段会从_source中提取出来,而不是返回整个 _source 字段。
储存字段:除了索引字段的值,你也可以选择 储存 字段的原始值以备日后取回。使用Lucene做后端的用户用存储字段来选择搜索结果的返回值,事实上, _source字段
是一个储存字段。
在Elasticsearch中,单独设置储存字段不是一个好做法。完整的文档已经被保存在_source 字段中,通常最好的办法会是使用 _source参数来过滤你需要的字段。

元数据:_all字段

_all字段:一个所有其他字段值的特殊字符串字段。query_string在没有指定字段时默认用_all字段查询。
_all字段在新应用的探索阶段比较管用,当你还不清楚最终文档的结构时,可以将任何查询用于这个字段,就有机会得到你想要的文档:
GET /_search
{
"match" : {
"_all" : "john smith marketing"
}
}
随着你应用的发展,搜索需求会变得更加精准。你会越来越少的使用_all字段。_all是一种简单粗暴的搜索方式。通过查询独立的字段,你能更灵活、强大和精准的控制搜
结果,提高相关性。
提示:【相关性】考虑的一个最重要的原则是字段的长度:字段越短,就越重要。在较短的 title 字段中的短语会比较长的 content 字段中的短语显示更重要。而字段间的
差异在 _all 字段中就不会出现。
如果你决定不再使用 _all 字段,你可以通过下面的映射禁用它:
PUT /my_index/_mapping/my_type
{
"my_type" : {
"_all" : { "enabled" : false }
}
}
通过 include_in_all选项可以控制字段是否要被包含在 _all字段中,默认值是 true。在一个对象上设置include_in_all 可以修改这个对象所有字段的默认行为。
你可能想要保留 _all 字段来查询所有特定的全文字段,例如title,overview,summary和tags。相对于完全禁用 _all 字段,你可以先默认禁用 include_in_all 选项,而选
段上启用 include_in_all。
PUT /my_index/_mapping
{
"my_type" : {
"include_in_all" : false,
"properties" : {
"title" : {
"type" : "string",
"include_in_all" : true
},
....
}
}
}
谨记,_all字段仅仅是一个经过分析的 string 字段。它使用默认的分析器来分析它的值,而不管这值本来所在的字段指定的分析器。而且像所有string类型字段一样,你可
置_all 字段使用的分析器:
PUT /my_index/my_type/_mapping
{
"my_type" : {
"_all" : { "analyzer" : "whitespace" }
}
}

文档ID

文档唯一标识由四个元数据字段组成:
_id:文档的字符串ID
_type:文档的类型名
_index:文档所在的索引
_uid:_type 和_id 连接成的type#id
默认情况下,_uid是被保存(可取回)和索引(可搜索)的。_type字段被索引但是没有保存,_id和_index字段则既没有索引也没有存储,他们并不是真实存在的。
尽管如此,你仍然可以像真实字段一样查询 _id 字段。Elasticsearch使用 _uid字段来追溯 _id。虽然你可以修改这些字段的 index 和 store 设置,但是基本上不需要这么做
_id字段有一个你可能用得到的设置: path 设置告诉 Elasticsearch 它需要从文档本省的哪个字段中生成 _id。
PUT /my_index
{
"mappings" : {
"my_type" : {
"_id" : {
"path" : "doc_id"
},
"properties" : {
"doc_id" : {
"type" : "string" ,
"index" : "not_analyzed"
}
}
}
}
}
注意:从doc_id字段生成 _id。
然后,当你索引一个文档时:
POST /my_index/my_type
{
"doc_id" : "123"
}
_id 值由文档主体的doc_id字段生成。
警告:虽然这样很方便,但是注意它对 bulk 请求有个轻微的性能影响。处理请求的节点将不能仅靠解析元数据行来决定将请求分配给哪一个分片,而需要解析整个文档主体。

动态映射

当Elasticsearch遭遇一个位置的字段时,它通过【动态映射】来确定字段的数据类型且自动将该字段加到类型映射中。
有时这是理想的行为,有时却不是。或许你不知道今后会有哪些字段加到文档中,但是你希望他们能自动被索引。或许你仅仅想忽略他们。特别是当你使用Elasticsearch作为主数据源时,你希望位置字段能抛出一个异常来警告你。
幸运的是,你可以通过 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!"
}
备注:将dynamic设置成false完全不会修改_source字段的内容。_source将仍旧保持你索引时的完整JSON文档。然而,没有被添加到映射的未知字段将不可被搜索。

自定义动态索引

如果你想在运行时的增加新的字段,你可能会开启动态索引。虽然有时动态映射的规则显得不那么智能,幸运的是我们可以通过设置来自定义这些规则。

日期检测

当Elasticsearch遇到一个新的字符串字段时,他会检测这个字段是否包含一个可识别的日期,比如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 字段,你得手动添加它。
提示:Elasticsearch判断字符串为日期的规则可以通过 dynamic_date_formats 设置来修改。

动态模板

使用 dynamic_templates,你可以完全控制新字段的映射额,你设置可以通过字段名或数据类型应用一个完全不同的映射。
每个模板都有一个名字用来描述这个模板的用途,一个 mapping 字段用于指明这个映射怎么使用,和至少一个参数(例如 match)来定义这个模板适用于哪个字段。
模板按照顺序来检测,第一个匹配的模板会被启用。例如,我们给 string 类型字段定义两个模板:
  • es:字段名以_es结尾需要使用 spanish分析器。
  • en:所有其他字段使用english分析器。
我们将 es 模板放在第一位,因为他比匹配所有字符串的 en模板更特殊一点。
PUT /my_index
{
"mappings" : {
"my_type" : {
"dynamic_templates" : [
{ "es" : {
"match" : "*_es",                        <1>
"match_mapping_type" : "string",
"mapping" : {
"type" : "string" ,
"analyzer" : "spanish"
}
}},
{ "en" : {
"match" : "*",                             <2>
"match_mapping_type" : "string" ,
"mapping" : {
"type" : "string",
"analyzer" : "english"
}
}}
]
}
}
}
<1> 匹配字段名以 _es 结尾的字段。
<2> 匹配所有字符串类型字段。
match_mapping_type 允许你限制模板只能使用在特定的类型上,就像由标准动态映射规则检测的一样(例如string和long),match 参数只匹配字段名, path_match 参数则匹配字段在一个对象中的完整路径,所以 address.*.name 规则将匹配一个这样的字段:
unmatch和path_unmatch规则将用于排除未被匹配的字段。

默认映射

通常,一个索引的所有类型具有共享的字段和设置。用 _default_ 映射来指定公有设置会更加方便,而不是每次创建新的类型时重复操作。 _default映射像新类型的模板。所有在 _default_ 映射之后的类型将包含所有的默认设置,除非在自己的类型映射中明确覆盖这些配置。
例如,我们可以使用 _default_映射对所有类型禁用 _all 字段,而只在blog 字段上开启它:
PUT /my_index
{
"mappings" : {
"_default_" : {
"_all" : { "enabled" : false }
},

"blog" : {
"_all" : { "enabled" : true }
}
}
}
_default_ 映射也是定义索引级别的动态模板的好地方。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值