赞
踩
动态映射的核心是在自动检测字段类型后添加新字段
哪些字段类型支持动态检测呢?
答:boolean类型、float类型、long类型、Object类型、Array类型、date类型、字符串类型。除此之外的类型是不支持动态检测匹配的,会适配为text类型
1)字段匹配不准确,如将date类型匹配为keyword类型。
###字段匹配不正确
DELETE my_index_0505
PUT my_index_0505/_doc/1
{
"create_date": "2020-12-26 12:00:00"
}
GET my_index_0505/_mapping
获取映射发现,create_date是text和keyword组合类型,不是我们期望的date类型。
那么如何解决呢?方案如下(需要提前设置匹配规则)。
####提前设置匹配规则 DELETE my_index_0505 PUT my_index_0505 { "mappings": { "dynamic_date_formats": ["yyyy-MM-dd HH:mm:ss"] } } PUT my_index_0505/_doc/1 { "create date": "2020-12-26 12:00:00" } GET my_index_0505/_mapping
2)字段匹配不精准,可能不是用户期望的。
举例:用户期望text类型支持ik中文分词,但默认的是standard标准分词器。对此当然也有解决方案,可借助动态模板实现。
3)占据多余的存储空间。
举例:string类型匹配为text和keyword两种类型,但实际用户极有可能只期望排序和聚合的keyword类型,或者只需要存储text类型,如网页正文内容只需要全文检索,不需要排序和聚合操作。
4)映射可能错误泛滥。
不小心写错查询语句,由于使用了PUT操作,导致映射变得非常混乱。
我们在数据建模前,需要明确文档中各个字段的类型。如何严格禁止动态添加字段或者忽略动态添加字段呢?这些都是静态映射要解决的问题。
对于该场景,可以将dynamic参数设置为false(表示忽略新字段),或者将dynamic参数设置为strict(表示如果遇到未知字段,则引发异常)。
例如,在"dynamic":false
后,cont字段可以写入,但不能被检索。
###创建索引,指定dynamic为false PUT my_index_0506 { "mappings": { "dynamic": false, "properties": { "user": { "properties": { "name": { "type": "text" }, "social_networks": { "dynamic": true, "properties": { } } } } } } } ####数据可以写入成功 PUT my_index_0506/_doc/1 { "cont": "Each document has metadata associated" } ###检索不能找回数据,核心原因在于cont是未映射字段 POST my_index_0506/_search { "profile": true, "query": { "match": { "cont": "document" } } } ### 可以返回结果 GET my_index_0506/_doc/1 ####mapping中并没有 cont GET my_index_0506/_mapping
代码中"profile":true辅助我们看到底层的检索逻辑,而不能召回数据的核心原因在于cont是未映射的字段。
POST my_index_0506/_doc { "user.social_networks.test": "Each document has metadata associated" } GET my_index_0506/_doc/CsS4cY8BA63nf2PurWKA POST my_index_0506/_search { "profile": true, "query": { "match": { "user.social_networks.test": "document" } } }
对于social_networks对象设置为"dynamic": true
,可以动态映射字段类型
GET my_index_0506/_mapping
如果"dynamic":"strict"
,那么写入映射中未定义的字段会怎么样呢?
###创建索引,指定dynamic为false PUT my_index_0507 { "mappings": { "dynamic": "strict", "properties": { "user": { "properties": { "name": { "type": "text" }, "social_networks": { "dynamic": true, "properties": { } } } } } } } ####数据写入失败 PUT my_index_0507/_doc/1 { "cont": "Each document has metadata associated" }
官方文档强调已经定义的字段在大多数情况下不能更新,除非通过reindex操作来更新映射。
但以下3种情况例外。
❑Object对象可以添加新的属性。
❑在已经存在的字段里面可以添加fields,以构成一个字段多种类型。
❑ignore_above是可以更新的。
###创建索引,验证映射更新 PUT my_index_0508 { "mappings": { "properties": { "name": { "properties": { "first": { "type": "text" } } }, "user_id": { "type": "keyword" } } } } ### 映射可以更新成功 PUT my_index_0508/_mapping { "mappings": { "properties": { "name": { "properties": { "first": { "type": "text", "fields": { "field": { "type": "keyword" } } }, "last":{ "type" : "text" } } }, "user_id": { "type": "keyword" } } } }
在以上实战中,对应第一种情况,Object对象可以添加新的属性,添加了last字段。对应第二种情况,first添加了keyword类型,以组合构造fields。对应第三种情况,user_id添加了ignore_above。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。