elasticsearch 动态映射

动态映射

动态映射的核心是在自动检测字段类型后添加新字段

哪些字段类型支持动态检测呢?
答: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。

  • 17
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值