当前位置:   article > 正文

elasticsearch 动态映射_es新增字段dynamic

es新增字段dynamic

动态映射

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

哪些字段类型支持动态检测呢?
答: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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

在这里插入图片描述
获取映射发现,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

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

在这里插入图片描述
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

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46

在这里插入图片描述
代码中"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"
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

在这里插入图片描述
对于social_networks对象设置为"dynamic": true,可以动态映射字段类型

GET my_index_0506/_mapping
  • 1

在这里插入图片描述

如果"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"
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

在这里插入图片描述

实战:映射创建后还可以更新吗

官方文档强调已经定义的字段在大多数情况下不能更新,除非通过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"
            }
        }
    }
}


  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48

在以上实战中,对应第一种情况,Object对象可以添加新的属性,添加了last字段。对应第二种情况,first添加了keyword类型,以组合构造fields。对应第三种情况,user_id添加了ignore_above。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/喵喵爱编程/article/detail/860849
推荐阅读
相关标签
  

闽ICP备14008679号