05.Elasticsearch应用(五)

Elasticsearch应用(五)

1.目标

咱们这一章主要学习Mapping(映射)

2.介绍

Mapping是对索引库中文档的约束,类似于数据表结构,作用如下:

  • 定义索引中的字段的名称
  • 定义字段的数据类型,例如字符串,数字,布尔等
  • 字段,倒排索引的相关配置(Analyzer)

3.映射类型

动态映射

介绍

在关系型数据库中,需要事先创建数据库,然后在该数据库下创建数据表,并创建表字段,类型,长度,主键等,最后才能基于表插入数据。而Elasticsearch中不需要定义Mapping映射,在文档写入Elasticsearch时,会根据文档自动识别类型,这种机制称之为动态映射

缺点

动态映射(Dynamic Mapping)的机制,使得我们无需手动定义Mappings,Elasticsearch会自动根据文档信息,推算出字段的类型。但是有时候会推算的不对,例如地理位置信息。当类型如果设置不对时,会导致一些功能无法正常运行,例如Range查询

自动识别的类型

在这里插入图片描述

静态映射

静态映射是在Elasticsearch中也可以实现定义好映射,包含文档的各字段类型,分词器等,这种方式称之为静态映射

4.常见的字段类型

核心类型 具体类型 说明
字符串类型 text 可分词的文本
不分词的字符串 keyword 精确值,例如:品牌,国家,IP地址等 不能被分词
整数类型 long,integer,short,byte 在ES中id应该是个字符串keyword而不是数值类型
浮点类型 double,float,half_float,scaled_float
日期类型 date,date_nanos
布尔类型 boolean
数组类型 array 数组类型不存在,里面是什么就是很么类型
对象类型 object
地理位置类型 geo_point,geo_shape
补全类型 completion 自动补全功能所需要的类型
二进制类型 binary
范围类型 integer_range,float_range,long_range,double_range,date_range,ip_range
JSON对象数组 nested

5.常见的Mapping属性

属性 含义
type 字段数据类型
index 是否创建索引,默认为true
analyzer 使用那种分词器
properties 该字段的子字段
copy_to 字段拷贝,可以将当前字段拷贝到指定字段
store 是否单独存储。如果设置为true,则该字段能够单独查询
boost 控制算分
coerce
doc_values
dynamic 动态映射设置
eager_global_ordinals
enabled
fielddata
fields
format
ignore_above
ignore_malformed
index_options 控制倒排索引记录的内容
index_phrases
index_prefixes
meta
normalizer
norms
null_value 对NULL值进行搜索
position_increment_gap
search_analyzer
similarity
term_vector

6.能否后期更改Mapping的字段类型

两种情况

  1. 新增字段
  2. 对已有字段修改(有数据写入后)

新增字段

  1. dynamic设为true时,一旦有新增字段的文档写入,Mapping也同时被更新
  2. dynamic设为false,Mapping不会被更新,新增字段的数据无法被索引,但是信息会出现在_source中
  3. dynamic设置成strict(严格控制策略),文档写入失败,抛出异常

对已有字段修改(有数据写入后)

  1. Lucene实现的倒排索引,—旦生成后,就不允许修改
  2. 如果希望改变字段类型,必须Reindex APl,重建索引

原因

  1. 如果修改了字段的数据类型,会导致已被索引的数据无法被搜索
  2. 但是如果是增加新的字段,就不会有这样的影响

总结

在这里插入图片描述

7.对已有字段的mapping修改

步骤

  1. 如果要推倒现有的映射, 你得重新建立一个静态索引
  2. 然后把之前索引里的数据导入到新的索引里
  3. 删除原创建的索引
  4. 为新索引起个别名, 为原索引名

索引数据迁移API

POST _reindex
{
	"source":{
		"index":"user"
	},
	"dest":{
		"index":"user2"
	}
}

使用别名兼容原有的索引

PUT /user/_alias/user

8.Dynamic Template

需求

我们可以使用动态模板来告诉es,一些字段需要动态映射成相关类型,例如根据类型来判断,或者只要是根据字段名称包含ip的,动态的给一个IP的类型,而这种思路就是es提供的动态模板,Dynamic templates

介绍

动态模板是针对某个具体的索引来设定的,即在创建某个具体的索引时指定

适用场景

  • 根据ES自动识别字段类型的这个特性,去设置一些特殊字段的名称为某些特定的类型
  • 设置所有字符串类型的字段都为 keyword
  • is 开头的字符串都设置成为 boolean 类型

三种规则

  • match_mapping_type
  • match and unmatch
  • path and path_unmatch

match_mapping_type

根据文档字段的类型进行动态映射。在这种方式下,会对JSON的数据类型进行动态定义es的数据类型。从前面,我们值JSON的数据是没有类型之分,所以es会动态根据数据本身的类型来进行映射

PUT es-learn-000002
{
  "mappings": {
    "dynamic_templates": [
      {
        "integers": {
          "match_mapping_type": "long",
          "mapping": {
            "type": "integer"
          }
        }
      }
    ]
  }
}

match and unmatch

根据名称的规则,来定义一些特定的动态映射,这便是动态模板的第二种方式match and unmatch。在这种方式下,字段名称的匹配支持正则表达式。match表示当字段名称符合的规则时应用,unmatch表示当字段符合规则时不应用这个动态映射

PUT es-learn-000003
{
  "mappings": {
    "dynamic_templates": [
      {
        "email_keyword": {
          "match":   "*_email",
          "mapping": {
            "type": "keyword"
          }
        }
      },
      {
        "ip_rule": {
          "match":   "*_ip",
          "unmatch": "long_*",
          "mapping": {
            "type": "ip"
          }
        }
      }
    ]
  }
}

注意

当我们插入嵌套的JSON的时候,动态映射的规则是应用在嵌套JSON里的对象

path_match and path_unmatch

我们知道JSON可以保存复杂的嵌套关系,那么如果我们想依据嵌套关系制定相关的动态映射的规则,该怎么处理呢?path_match和path_unmatch的用法同match和unmatch的用法相似,使用正则表达式来进行匹配。只是match匹配的是字段的值,而path_match匹配的是JSON的嵌套关系

以下这段代码想实现的效果是,name下的嵌套对象,并且不是middle名字的类型都为keyword

PUT es-learn-000005
{
  "mappings": {
    "dynamic_templates": [
      {
        "middle_name_key": {
          "path_match":   "name.*",
          "path_unmatch": "*.middle",
          "mapping": {
            "type": "keyword"
          }
        }
      }
    ]
  }
}

9.索引基础操作

创建索引的时候指定Mapping

PUT /[索引名称]
{
    "mappings":{
        "properties":{
            "字段名":{
                "type":"text",
                "analyzer":"ik_smart"
            },
            "字段名2":{
                "type":"keyword",
                "index":false
            },
            "字段名3":{
                "properties":{
                    "子字段":{
                        "type":"keyword"
                    }
                }
            }
        } 
    }
}

获取索引的字段Mapping

介绍

检索一个或多个字段的映射定义。如果您不需要索引的完整映射或索引包含大量字段,这将很有用

请求路径
GET /_mapping/field/[字段名]

GET /[索引名]/_mapping/field/[字段名]
请求示例
GET publications/_mapping/field/title
GET publications/_mapping/field/author.id,abstract,name
GET publications/_mapping/field/a*

获取某个索引的映射信息

GET /索引名/_mapping

10.Mapping属性解读

字段拷贝(copy_to)

介绍
  1. 该参数允许将多个字段的值复制到copy_to的字段上
  2. copy_to的字段支持查询
  3. 如果有多个字段需要查询,可以尝试把多个字段的值拷贝到一个新字段上
  4. 可以将相同的值复制到多个字段, “copy_to”: [ “field_1”, “field_2” ]
示例
PUT /[索引名]
{
    "mappings":{
        "properties":{
            "name":{
                "type":"text",
                "analyzer":"ik_max_word",
                "copy_to":"all"
            },
            "business":{
                "type":"keyword",
                "copy_to":"all"
            },
            "all":{
                "type":"text",
                "analyzer":"ik_max_word"
            }
        }
    }
}

index

介绍

控制当前字段是否被索引,默认为true。如果设置为false,该字段不可被搜索

示例
PUT /[索引名]
{
    "mappings":{
        "properties":{
            "name":{
                "type":"text",
                "index":false
            }
        }
    }
}

index_options

介绍

控制倒排索引记录的内容

可选值
  1. docs: 记录doc id
  2. freqs: 记录doc id和term frequencies(词频)
  3. positions: 记录doc id / term frequencies / term position
  4. offsets: doc id / term frequencies / term posistion / character offects
  5. 注意: text类型默认记录postions,其他默认为docs。记录内容越多,占用存储空间越大
示例
PUT /[索引名]
{
    "mappings":{
        "properties":{
            "name":{
                "type":"text",
                "index_options":"offsets"
            }
        }
    }
}

null_value

介绍

需要对NULL值进行搜索,只有keyword类型支持设计Null_value

示例
PUT /[索引名]
{
    "mappings":{
        "properties":{
            "name":{
                "type":"keyword",
                "null_value":"NULL"
            }
        }
    }
}

boost

介绍

在查询时,可以增加字段的算分,默认为1

请求格式
# 创建索引时候指定
PUT /<index>
{
  "mappings": {
    "properties": {
      "<field>": {
        "type": "text",
        "boost": 2 
      }
    }
  }
}

# 查询时指定
POST _search
{
    "query": {
        "match" : {
            "title": {
                "query": "quick brown fox",
                "boost": 2
            }
        }
    }
}
注意
  • 不提升prefix,range,fuzzy查询的分数
  • 不建议使用index time提升。而是在search time时使用

fields

介绍

text字段类型不能被排序和聚合如果要text字段能被排序或聚合可以使用fields

请求格式
PUT /<index>
{
  "mappings": {
    "properties": {
      "<field>": {
        "type":     "text",
        "fields":{
          "<child_field>":{
            "type":"keyword"
          }
        }
      }
    }
  }
}