Elastic Seach基础—映射(Mapping)

Elastic Search的映射(Mapping)用于在一个索引中把文档划分为具有逻辑关系的分组,类似于数据库的表结构,是一个不可或缺的一部分。

自动生成

ES的Mapping可以类似于MongoDB那样自动生成,例如我们首先插入一条数据。

PUT?twitter/_doc/1
{
??"user_name":?"kimchy",
??"age":25,
}

此时,可以通过API查看mapping设置

GET?/twitter/_mapping

{
????"twitter":?{
????????"mappings":?{
????????????"properties":?{
????????????????"age":?{?"type":?"long"??},
????????????????"user_name":?{?"type":?"text",???"fields":?{?"keyword":?{?"type":?"keyword",??"ignore_above":?256?}?}
????????????????}
????????????}
????????}
????}
}

手动生成

自动生成可以大大减少我们创建mapping的步骤,但很多时候我们需要更精细化的设置,可以在创建索引的时候设置mapping:

PUT?/twitter
{
????"mappings":?{
????????"properties":?{
????????????"age":?{?"type":?"long"?},
????????????"user_name":?{?"type":?"keyword",?"ignore_above":?256?}
????????}
????}
}

也可以将创建索引和创建映射作为两步实现:

PUT?/twitter

PUT?/twitter/_mapping
{
??"properties":?{?"age":?{"type":?"long"?},
????"user_name":?{?"type":?"keyword",?"ignore_above":?256?}
??}
}

修改映射

Elastic Search允许增加字段的索引,可以通过Put接口增加字段的映射设置:

PUT?/twitter/_mapping
{
??"properties":?{
????"tag":?{?"type":?"text"?}
??}
}

另外,Elastic Search也允许对已有字段增加类型(下文的多字段)。

但是,Elastic Search不允许对索引修改映射,我们再次执行创建mapping语句的时候会报错,对于修改映射的需求,ES提供了_reindex的api,具体的方式是:

  1. 创建一个新索引
  2. 通过_reindex API将数据从老索引移动到新索引

POST?/_reindex
{
????"source":?{?"index":?"twitter"?},
????"dest":?{?"index":?"twitter2"?}
}

具体方法可以参考官方文档: Reindex is coming!

简单类型

对于映射设置,最常用的就是设置其字段类型,例如:

"properties":?{
????"age":?{?"type":?"long"?},
????"user_name":?{?"type":?"keyword"?}
}

对于简单类型,ES对于其分类如下:

多字段

对于字符串类型,可以把它定义成两种类型: text和keyword。

  • text:只匹配其部分信息,内容会被分词,如文章。不支持聚合
  • keyword:必须完整匹配的内容,如邮箱,身份证号,部分匹配会导致错误的结果。支持聚合

这两种类型都是比较常用的,但有的时候,对于一个字符串字段,我们可能希望他两种都支持,此时,可以利用其多字段特性

"properties":?{
????"user_name":?{
????????"type":?"text",
????????"fields":?{
????????????"keyword":?{
????????????????"type":?"raw",
????????????????"ignore_above":?256
????????????}
????????}

}

对于user_name这个字段,其类型是text,同时又定义了一个"raw"的keyword的关键字段,当需要完全匹配的时候,可以通过user_name.raw查询。

更多内容可以参考其官方文档:Field datatypes

复合类型

ES支持三种复合类型:

  1. Array 数组型????:????支持数组形式,不需要一个专有的字段数据类型
  2. Object 对象型:????object数据类型:表现形式其实就是单一的JSON对象
  3. Nested 嵌套型:????nested数据类型:表现形式是多个Object型组成的一个数组

Array 数组型

Elasticsearch中,没有特定的array类型。默认情况下,任何字段都可以包含0个或者更多值,但是,所有array中的值必须具有相同的数据类型,例如:

  • 字符串数组:["one", "two"]
  • 整数数组:[1,2]
  • 数组的数组:[1, [2, 3]],等价于[1,2,3]
  • 对象数组:[ { "name": "Mary", "age": 12 }, { "name": "John", "age": 10 }]

数组可以包含null值,这些值可以由配置的null_value替换或完全跳过。一个空的array []被视为不存在的字段-无值的字段。

Array类型是直接支持的,不需要特殊映射,如long类型的数组,直接映射成long即可。

Object 对象型

JSON文档本质上是分层的:文档包含内部对象,内部对象本身还包含内部对象。

PUT?/account/_doc/1

{
????"region":?"US",
????"manager":?{
????????"age":?30,
????????"name":?"John Smith"
????????}
????}
}

在内部,这个文档被索引为一个简单的、扁平的键值对列表,如下所示:

{
??"region":?"US",
??"manager.age":?30,
??"manager.name ":?"John Smith"
}

索引方法如下:

{
????"mappings":?{
????????"properties":?{
????????????"region":?{?"type":?"keyword"?},
????????????"manager":?{
????????????????"properties":?{
????????????????????????"age":?{?"type":?"integer"?},
????????????????????????"name":?{?"type":?"text"?}
?????????????????}
????????????}
????????}
????}
}

基本上是一个嵌套的方式,还是比较直观的。

Nested 嵌套型

由于对象扁平化存储,导致有的时候,对象数组并非你期望的那样工作,例如如下对象:

{
??"group":?"fans",
??"user":?[
????{
??????"first":?"John",
??????"last":?"Smith"
????},
????{
??????"first":?"Alice",
??????"last":?"White"
????}
??]
}

在内部被转化成如下格式的文档:

{
??"group":?"fans",
??"user.first":?[
????"alice",
????"john"
??],
??"user.last":?[
????"smith",
????"white"
??]
}

user.firstuser.last 扁平化为多值字段,alice 和 white 的关联关系丢失了。导致这个文档错误地匹配对 alice 和 smith 的查询

如果想并且保持数组中每个对象的独立性,在ElasticSearch中应该将其映射为nested对象类型而不是默认的object类型。

{
??"mappings":?{
????"properties":?{
??????"user":?{
????????"type":?"nested"
??????}
????}
??}
}

映射参数

除了前面列举的type参数外,还有不少其它参数可以设置,具体可以参考官方文档:Mapping parameters

其中大部分是可以不需要特殊设置的,采用默认参数即可,这里列举一下一些可能会用到的属性:

enable

ElasticSearch默认会索引所有字段,但是,有的信息是只需要存储,并不需要索引的。例如,一些链接url,往往只会用来读取,并不会作为搜索字段。在这些字段上建索引就会有无谓的性能浪费。

此时,我们可以设置enable属性为false,此时 Elasticsearch 完全跳过字段内容的分析,从而提高性能。

{
??"mappings":?{
????"properties":?{
??????"url":?{
????????"type":?"object",
????????"enabled":?false
??????}
????}
??}
}

需要注意的是,它只能使用在类型为object的字段上。设置为object并不影响任何功能,并且能存储任何类型,本身也能简化我们的mapping。

index

index的用法和enable非常相似,设置为index为false的字段不参与索引,但它是设置在非object类型上的。

至于它们有没有进一步的区别,官方也语焉不详,实际使用感觉没有啥太大区别,等有进一步结论后再完善本文。

analyzer

分析器用于设置字段的分词方法,它是ElasticSearch经常使用到的高级设置,具体内容在下一篇博文中介绍。

映射相关接口

关于映射更多接口,可以参考官方文档:Put mapping API

Elastic Seach基础—映射(Mapping)

上一篇:微信页面的分享,设置分享信息以及监听分享


下一篇:Mac电脑小知识:如何强制关闭苹果Mac电脑后台程序