Mapping类似于数据库中的表定义,主要有以下几个作用:
Mapping设置会把JSON文档映射成Lucence所需要的扁平格式。
es7.0开始,一个索引只能有一个type,所以就可以说Mapping属于索引的type,每个文档都属于一个Type,每个Type都有一个Mapping。听起来好像很难理解,我们接着看。
简单类型
复杂类型:对象类型、嵌套类型
特殊类型:geo_point 、geo_shape、percolator等
ES中的字段类型详解.
什么是Dynamic Mapping? 它主要有以下几个作用:
JSON类型 | ES类型 |
---|---|
字符串 | 匹配日期,设置为Date。匹配数字,设置为float或者long(默认关闭)。会为字符串类型设置为Text,并增加keyword子字段。 |
布尔值 | boolean |
浮点数 | float |
整数 | long |
对象 | Object |
数组 | 有第一个非空数值的类型所决定 |
空 | 忽略 |
例子:我们新创建一个索引,不指定mapping,写入一个文档,查看ES为我们自动生成的mapping。
查看mapping:get index/_mapping
put index
put index/_doc/1
{
"firstName":"程",
"lastName":"大帅",
"date":"2021-12-01T00:00:00.000Z",
"age":18,
"isvid":true
}
-------------------------------------
{
"index" : {
"mappings" : {
"properties" : {
"age" : {
"type" : "long"
},
"date" : {
"type" : "date"
},
"firstName" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"isvid" : {
"type" : "boolean"
},
"lastName" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
}
}
}
}
}
可以看到时间格式的字段,es为我们转成了date类型,age转成了数字,字符串为我们设置了text字段和子类型keyword,布尔值自动映射为boolean类型。
上述示例我们可以看到,新建一个索引并插入文档后,ES会自动帮我们生成一个mapping,有时候自动生成的mapping字段格式并不是我们想要的,那么能否对mapping设置进行修改呢?
两种情况:
ES的搜索基于Lucene,倒排索引一旦生成之后,就不允许被修改
如果希望改变已有数据的字段类型,必须重建索引 Reindex
ES之所以有上述规则,是因为如果字段的数据类型能够被随意更改,那么就会导致倒排索引的紊乱,影响到搜索,甚至无法被搜索。
但是如果时新增加的字段,相应的字段数据并不存在,则不会有这样的影响
我们可以在创建索引的时候指定Dynamic
PUT index
{
"mappings":{
"dynamic":"false"
}
}
也可以对索引mapping的dynamic属性进行修改
PUT index/_doc/_mapping?include_type_name=true
{
"dynamic":"false"
}
Dynamic有三个值可以设置:true、false、strict
设置为true时
:文档可索引、字段可索引、mapping允许被更新。
设置为false时
:文档可索引、字段不可索引、mapping不允许被更新。
设置为true时
:文档不可索引、字段不可索引、mapping不允许被更新。
其实对于实际开发过程中,我们有一些小诀窍来减少创建mapping的工作量。
在我们设定一个mapping文件的时候,可以显示的指定某些字段不被可以被搜索。
比如我设置了firstname
字段的index为false。
PUT index/_doc/_mapping?include_type_name=true
{
"dynamic":"false",
"properties":{
"age":{
"type":"long"
},
"date":{
"type":"date"
},
"firstName":{
"type":"text",
"index":false
},
"isvid":{
"type":"boolean"
},
"lastName":{
"type":"text"
}
}
}
---------------------------------------
get index/_search
{
"query":{
"match":{
"firstName":"程"
}
}
}
"status" : 400
failed to create query: Cannot search on field [firstName] since it is not indexed.
当我们对设置了"index":false
的字段进行搜索的时候,直接报错400。
索引配置(Index Options):可以控制倒排索引记录的内容。记录的内容越多,所占用的存储空间就越大。不同的索引配置也可以达到性能优化的目的
。
记录doc id
记录doc id +(term出现频率)term frequencies
记录 doc id +(term出现频率)term frequencies + (term所在语句位置)term position
记录 doc id +(term出现频率)term frequencies + (term所在语句位置)term position + (词条所在的偏移量)character offsets
示例:
PUT index/_doc/_mapping?include_type_name=true
{
"dynamic":"false",
"properties":{
"age":{
"type":"long"
},
"date":{
"type":"date"
},
"firstName":{
"type":"text",
"index":false
},
"isvid":{
"type":"boolean"
},
"lastName":{
"type":"text"
"index_options":"offsets"
}
}
}
有时候我们插入的文档,某些字段是null,但是需求需要对其进行搜索,那么我们就可以给字段指定"null_value:"xxx""
,搜索时让字段匹配xxx
即可搜索到null值。
注意:只有keyword类型支持null_value
PUT index2
{
"mappings":{
"properties":{
"date":{
"type":"date"
},
"firstName":{
"type":"keyword",
"null_value":"N"
},
"lastName":{
"type":"text"
}
}
}
}
--------------------
GET index2/_search
{
"query":{
"match":{
"firstName":"N"
}
}
}
copy to可以满足一些特定的搜索需求,它的作用是:将多个字段的数据拷贝到目标字段中,目标字段可以用于搜索,拷贝字段不在_source中保存。
PUT index
{
"mappings":{
"properties":{
"firstName":{
"type":"text",
"copy_to":"fullName"
},
"lastName":{
"type":"text",
"copy_to":"fullName"
}
}
}
}
---------------------------
put index/_doc/1
{
"firstName":"程",
"lastName":"大帅"
}
----我们就可以使用fullName进行搜索----
get index/_search
{
"query":{
"match":{
"fullName":"程"
}
}
我们get index/_mapping
看一下,可以看到fullName
被放进mapping内,但是搜索结果的_source中是没有这个字段的
{
"index" : {
"mappings" : {
"properties" : {
"firstName" : {
"type" : "text",
"copy_to" : [
"fullName"
]
},
"fullName" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"lastName" : {
"type" : "text",
"copy_to" : [
"fullName"
]
}
}
}
}
}
ES中不提供专门的数组类型。任何字段都可以包含多个相同字段的数据。
比如还是上面创建的索引,我现在将 程二帅 也想保存到ES中,就可以这样写。
put index/_doc/2
{
"firstName":"程",
"lastName":["大帅","二帅"]
}
----------------------------
get index/_search
{
"query":{
"match":{
"fullName":"帅"
}
}
}