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的字段类型
两种情况
- 新增字段
- 对已有字段修改(有数据写入后)
新增字段
- dynamic设为true时,一旦有新增字段的文档写入,Mapping也同时被更新
- dynamic设为false,Mapping不会被更新,新增字段的数据无法被索引,但是信息会出现在_source中
- dynamic设置成strict(严格控制策略),文档写入失败,抛出异常
对已有字段修改(有数据写入后)
- Lucene实现的倒排索引,—旦生成后,就不允许修改
- 如果希望改变字段类型,必须Reindex APl,重建索引
原因
- 如果修改了字段的数据类型,会导致已被索引的数据无法被搜索
- 但是如果是增加新的字段,就不会有这样的影响
总结
7.对已有字段的mapping修改
步骤
- 如果要推倒现有的映射, 你得重新建立一个静态索引
- 然后把之前索引里的数据导入到新的索引里
- 删除原创建的索引
- 为新索引起个别名, 为原索引名
索引数据迁移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)
介绍
- 该参数允许将多个字段的值复制到copy_to的字段上
- copy_to的字段支持查询
- 如果有多个字段需要查询,可以尝试把多个字段的值拷贝到一个新字段上
- 可以将相同的值复制到多个字段, “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
介绍
控制倒排索引记录的内容
可选值
- docs: 记录doc id
- freqs: 记录doc id和term frequencies(词频)
- positions: 记录doc id / term frequencies / term position
- offsets: doc id / term frequencies / term posistion / character offects
- 注意: 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" } } } } } }