什么叫做文档映射??
ES的文档映射(mapping)机制用于进行字段类型或分词器确认,将每个字段匹配为一种确定的数据类型。-就相当于在设计表的时候为字段指定类型.
ES支持哪些数据类型??
① 基本字段类型
字符串:text(分词),keyword(不分词) StringField(不分词文本),TextFiled(要分词文本)
text默认为全文文本,keyword默认为非全文文本
数字:long,integer,short,double,float
日期:date
逻辑:boolean
② 复杂数据类型
对象类型:object
数组类型:array
地理位置:geo_point,geo_shape
默认映射
查看索引类型的映射配置:GET {indexName}/_mapping/{typeName}
ES在没有配置Mapping的情况下新增文档,ES会尝试对字段类型进行猜测,并动态生成字段和类型的映射关系。
JSON type
Field type
Boolean: true or false
"boolean"
Whole number: 123
"long"
Floating point: 123.45
"double"
String, valid date:"2014-09-15"
"date"
String: "foo bar"
"string"
正常来说应该先为文档类型(相当于数据库中标)指定里面字段类型.但是,原来我们操作的时候没有先指定?
为什么呢? --> 会走默认映射机制.
ES在没有配置Mapping的情况下新增文档,ES会尝试对字段类型进行猜测,并动态生成字段和类型的映射关系。
自定义映射
先来了解一下映射规则:
字段映射的常用属性配置列表 type
类型:基本数据类型,integer,long,date,boolean,keyword,text...
enable
是否启用:默认为true。 false:不能索引、不能搜索过滤,仅在_source中存储
头像路径
boost
权重提升倍数:用于查询时加权计算最终的得分。
format
格式:一般用于指定日期格式,如 yyyy-MM-dd HH:mm:ss.SSS
ignore_above
长度限制:长度大于该值的字符串将不会被索引和存储。
ignore_malformed
转换错误忽略:true代表当格式转换错误时,忽略该值,被忽略后不会被存储和索引。
include_in_all
是否将该字段值组合到_all中。
null_value
默认控制替换值。如空字符串替换为”NULL”,空数字替换为-1
store
是否存储:默认为false。true意义不大,因为_source中已有数据
index
索引模式:analyzed (索引并分词,text默认模式), not_analyzed (索引不分词,keyword默认模式),no(不索引)
analyzer
索引分词器:索引创建时使用的分词器,如ik_smart,ik_max_word,standard
search_analyzer
搜索分词器:搜索该字段的值时,传入的查询内容的分词器。
fields
多字段索引:当对该字段需要使用多种索引模式时使用。
如:城市搜索New York
"city": {
"type": "text",
"analyzer": "ik_smart",
"fields": {
"raw": {
"type": "keyword"
}
}
}
city分词
city.raw 不分词
那么以后搜索过滤和排序就可以使用city.raw字段名
映射测试
注意:如果已经有数据,不能直接做映射,先删除掉,在添加映射,再添加数据
1.简单类型映射
① 针对单个类型的映射配置方式
POST {indexName}/{typeName}/_mapping
{
"{typeName}": {
"properties": {
"id": {
"type": "long"
},
"content": {
"type": "text",
"analyzer": "ik_smart",
"search_analyzer": "ik_smart"
}
}
}
}
注意:你可以在第一次创建索引的时候指定映射的类型。此外,你也可以晚些时候为新类型添加映射(或者为已有的类型更新映射)。
你可以向已有映射中增加字段,但你不能修改它。如果一个字段在映射中已经存在,这可能意味着那个字段的数据已经被索引。如果你改变了字段映射,那已经被索引的数据将错误并且不能被正确的搜索到。
我们可以更新一个映射来增加一个新字段,但是不能把已有字段的类型那个从 analyzed 改到 not_analyzed。
② 同时对多个类型的映射配置方式(推荐)
PUT {indexName}
{
"mappings": {
"user": {
"properties": {
"id": {
"type": "integer"
},
"info": {
"type": "text",
"analyzer": "ik_smart",
"search_analyzer"
}
}
},
"dept": {
"properties": {
"id": {
"type": "integer"
},
...更多字段映射配置
}
}
}
}
2.对象及数组类型映射
① 对象的映射与索引
注意:Lucene不理解内置对象,一个lucene文档包含键值对的一个扁平化列表,以便于ES索引内置对象,它把文档转换为类似这样:
内置字段与名字相关,区分两个字段中相同的名字,可以使用全路径,例如user.girl.name
② 数组与对象数组 --> 注意:数组中元素的类型必须一致。
1)基础类型数组 - 只需映射里面内容的类型
2)对象数组 - 里面所有对象字段的类型是一样的-->只需映射一个就好
注意1:同内联对象一样,对象数组也会被扁平化索引
注意2:扁平化后,对象属性的相关性已经丢失,因为每个多值字段只是一个数值集,不是排序的数组。
比如查询:哪个女朋友的年龄是18岁? 这个是无法查询到答案,如果需要保留关系,需要使用嵌套对象nested objects。
3.全局映射 - 【 全局映射可以通过动态模板和默认设置两种方式实现 】
ex:员工类型的id要改为integer,而且部门类型的也要改为integer,甚至所有的都要改.这时每个都去修改非常麻烦.可以设置全局映射
①默认方式:_default_ [ 一般用来设置_all不要了 ]
索引下所有的类型映射配置会继承_default_的配置,user类型的文档中将不会合并所有字段到_all,而dept会 如:
②动态模板:dynamic_templates
注意:ES会默认把string类型的字段映射为text类型(默认使用标准分词器)和对应的keyword类型,如:
在实际应用场景中,一个对象的属性中,需要全文检索的字段较少,大部分字符串不需要分词,因此,需要利用全局模板覆盖自带的默认模板:
说明:上例中定义了两种动态映射模板string_as_text和string_as_keyword
在实际的类型字段映射时,会依次匹配:
①字段自定义配置
②全局dynamic_templates[string_as_text、string_as_keyword]
③索引dynamic_templates[...]
④ES自带的string类型映射,以最先匹配上的为准。
注意:索引库在创建的时候会继承当前最新的dynamic_templates,索引库创建后,修改动态模板,无法应用到已存在的索引库。
实践:映射的配置会影响到后续数据的索引过程,因此,在实际项目中应遵循如下顺序规则: 【有数据不做映射+根据优先级倒序来】
① 配置全局动态模板映射(覆盖默认的string映射)
② 配置字段映射(由于基本类型主要用于过滤和普通查询,因此,字段映射主要对需要全文检索的字段进行配置)
③ 创建、更新和删除文档
④ 搜索