Elastic Seach基础—映射(Mapping)

蹉跎莫遣韶光老,人生唯有读书好。这篇文章主要讲述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
  • 数字:long,?integer,?short,?byte,?double,?float,?half_float,?scaled_float
  • 日期:date
  • 布尔值:boolean
  • 二进制:binary
  • 范围:integer_range,?float_range,?long_range,?double_range,?date_range
多字段
对于字符串类型,可以把它定义成两种类型: 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.first和 user.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经常使用到的高级设置,具体内容在下一篇博文中介绍。
映射相关接口【Elastic Seach基础—映射(Mapping)】关于映射更多接口,可以参考官方文档:Put mapping API

    推荐阅读