• elasticsearch篇之mapping


    2018年05月17日 18:01:37  阅读数:444

    版权声明:文章内容来自于网络和博主自身学习体会,转载请注明出处,欢迎留言大家一起讨论学习~~ https://blog.csdn.net/sinat_35930259/article/details/80354732

    什么是mapping


    mapping是类似于数据库中的表结构定义,主要作用如下:

    • 定义index下的字段名
    • 定义字段类型,比如数值型、浮点型、布尔型等
    • 定义倒排索引相关的设置,比如是否索引、记录position等

    查看mapping


    GET /[index_name]/_mapping
    • 1

    这里写图片描述

    其中 keyword表示部分次的字符串类型

    自定义mapping


    api

    这里写图片描述

    说明

    mapping中的字段类型一旦设置,禁止直接修改,因为 lucene实现的倒排索引生成后不允许修改,应该重新建立新的索引,然后做reindex操作。

    但是可以新增字段,通过 dynamic 参数来控制字段的新增,这个参数的值如下:

    • true:默认值,表示允许选自动新增字段
    • false:不允许自动新增字段,但是文档可以正常写入,但无法对字段进行查询等操作
    • strict:严格模式,文档不能写入,报错 
      这里写图片描述

    示例

    首先创建名为 my_index的索引并设置mapping:

    PUT my_index
    {
      "mappings": {
        "doc": {
          "dynamic": false,
          "properties": {
            "title": {
              "type": "text"
            },
            "name": {
              "type": "keyword"
            },
            "age": {
              "type": "integer"
            }
          }
        }
      }
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    其中包含了 title、name、age三个字段

    查询索引的mapping设置:

    GET my_index/_mapping
    • 1

    这里写图片描述

    然后写入一个文档:

    PUT my_index/doc/1
    {
      "title": "hello world",
      "desc": "this is book"
    }
    • 1
    • 2
    • 3
    • 4
    • 5

    这里写图片描述

    注意,这里在mapping设置中,”dynamic”: false,表示在写入文档时,如果写入字段不存在也不会报错。这里的desc字段就是不存在的字段。

    查询一下写入的文档:

    GET my_index/doc/_search
    {
      "query": {
        "match": {
          "title": "hello"
        }
      }
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    这里写图片描述

    可以通过 title字段查询到文档的内容

    如果说想通过desc字段查询文档内容呢?当然是查不到的:

    GET my_index/doc/_search
    {
      "query": {
        "match": {
          "desc": "book"
        }
      }
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    这里写图片描述

    可以验证一下”dynamic”: strict模式: 
    首先删除索引:

    DELETE my_index
    • 1

    然后修改索引mapping设置:

    PUT my_index
    {
      "mappings": {
        "doc": {
          "dynamic": "strict",
          "properties": {
            "title": {
              "type": "text"
            },
            "name": {
              "type": "keyword"
            },
            "age": {
              "type": "integer"
            }
          }
        }
      }
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    在重新创建文档:

    PUT my_index/doc/1
    {
      "title": "hello world",
      "desc": "this is book"
    }
    • 1
    • 2
    • 3
    • 4
    • 5

    这里写图片描述

    在strict 模式下插入不存在的字段将会出现报错

    copy_to参数说明

    作用是将该字段的值复制到目标字段,实现类似_all的作用。不会出现在_source中,只能用来搜索。

    PUT my_index4
    {
      "mappings": {
        "doc": {
          "properties": {
            "first_name": {
              "type": "text"
              , "copy_to": "full_name"
            },
            "last_name": {
              "type": "text"
              , "copy_to": "full_name"
            },
            "full_name" : {
              "type": "text"
            }
          }
        }
      }
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    可以看到这个index中,full_name的内容就是从 first_name 和 last_name 中复制过来的。

    然后创建一个新的文档,文档只需要写first_name 和 last_name即可:

    PUT my_index4/doc/1
    {
      "first_name": "john",
      "last_name": "smith"
    }
    • 1
    • 2
    • 3
    • 4
    • 5

    最后查询一下文档的内容:

    GET my_index4/_search
    {
      "query": {
        "match": {
          "full_name": {
            "query": "john smith",
            "operator": "and"
          }
        }
      }
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    这个查询语句意思是:查询包含关键字john smith的文档,必须同时包含两个关键字才返回。

    这里写图片描述

    index参数

    index参数作用是控制当前字段是否被索引,默认为true,false表示不记录,即不可被搜索。

    PUT my_index5
    {
      "mappings": {
        "doc": {
          "properties": {
            "cookie": {
              "type": "text",
              "index": false
            },
            "content": {
              "type": "text",
              "index": true
            }
          }
        }
      }
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    这个index有两个字段,其中cookie设定为不可被搜索

    写入文档:

    PUT my_index5/doc/1
    {
      "cookie": "name=mike",
      "content": "hello world"
    }
    • 1
    • 2
    • 3
    • 4
    • 5

    尝试分别查询一下两个字段,看看区别:

    GET my_index5/_search
    {
      "query": {
        "match": {
          "cookie": "mike"
        }
      }
    }
    
    GET my_index5/_search
    {
      "query": {
        "match": {
          "content": "hello"
        }
      }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    这里写图片描述

    这里写图片描述

    当在es中存储了一些不想要被检索的字段如身份证、手机等,这是对于这些字段就可以使用index设置为false,这样有一定的安全性还可以节省空间

    index_options参数

    index_options的作用是用于控制倒排索引记录的内容,有如下四种配置:

    • docs:只记录doc id
    • freqs:记录doc id 和term frequencies
    • positions:记录doc id、 term frequencies和term position
    • offsets:记录doc id、 term frequencies、term position、character offsets

    text类型的默认配置为positions,其他默认为docs。记录的内容越多,占据的空间越大。

    这里写图片描述

    null_value参数

    这个参数的作用是当字段遇到null值的时候的处理策略,默认为null,即空值,此时es会忽略该值。可以通过这个参数设置某个字段的默认值。

    这里写图片描述

    数据类型


    核心数据类型

    • 字符串型:text、keyword(不会分词)
    • 数值型:long、integer、short、byte、double、float、half_float等
    • 日期类型:date
    • 布尔类型:boolean
    • 二进制类型:binary
    • 范围类型:integer_range、float_range、long_range、double_range、date_range

    复杂数据类型

    • 数组类型:array
    • 对象类型:object
    • 嵌套类型:nested object
    • 地理位置数据类型:geo_point、geo_shape
    • 专用类型:ip(记录ip地址)、completion(实现自动补全)、token_count(记录分词数)、murmur3(记录字符串hash值)

    多字段特性

    多字段特性(multi-fields),表示允许对同一字段采用不同的配置,比如分词。

    常见例子是对人名实现拼音搜索,只需要在人名中新增一个字段pinyin即可。但是这种方式不是十分优雅,multi-fields可以在不改变整体结构的前提下,增加一个子字段: 
    这里写图片描述

    Dynamic mapping


    自动识别规则

    在前面说过,在写入文档的时候如果index不存在的话es会自动创建这个索引。但是es是如何确定index字段的类型的呢?

    首先es可以自动识别文档字段的类型,这样可以降低用户的使用成本。 
    这里写图片描述

    es是依靠json文档的字段类型来实现自动识别字段类型的: 
    这里写图片描述

    这里写图片描述

    日期自动识别

    日期的自动识别可以自行配置日期的格式,默认情况下是:

    ["strict_date_opeional_time", "yyyy/MM/dd HH:mm:ss Z||yyyy/MM/dd Z"]
    • 1

    strict_date_opeional_time 是ISO 标准的日期格式,完整的格式如下:

    YYYY-MM-DDhh:mm:ssTZD(eg:1997-07-16y19:20:30+01:00)
    • 1

    dynamic_date_formats:可以自定义日期类型 
    date_detection:可以关闭日期自动识别机制(默认开启)

    首先创建一个日期自动识别的索引:

    PUT test_index
    {
      "mappings": {
        "doc": {
          "dynamic_date_formats": ["MM/dd/yyyy"]
        }
      }
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    然后创建一个文档:

    PUT test_index/doc/1
    {
      "create_time": "09/21/2016"
    }
    • 1
    • 2
    • 3
    • 4

    查看:

    GET test_index/_mapping
    • 1

    这里写图片描述

    关闭日期自动识别可以如下: 
    这里写图片描述

    数字自动识别

    字符串为数字的时候,默认不会自动识别为整型,因为字符串中出现数字是完全合理的。

    numeric_detection 可以开启字符串中数字的自动识别。 
    这里写图片描述

    Dynamic Templates


    Dynamic Templates 意为 动态模板,它的作用是允许根据es自动识别的数据类型、字段名等来动态设定字段类型。

    可以实现的效果如下:

    • 所有字符串类型都设置为keyword类型,即默认不分词
    • 所有以message开头的字段都设置为text类型,即分词
    • 所有以long_开头的字段都设置为long类型
    • 所有自动匹配为double类型的都设定为float类型,以节省空间

    API

    这里写图片描述

    匹配规则参数

    • match_mapping_type:匹配es自动识别的字段类型,如boolean、long等
    • match、unmatch:匹配字段名
    • path_match、path_unmatch:匹配路径

    举例

    字段类型匹配

    首先PUT一个文档,然后查看mapping:

    PUT test_index/doc/1
    {
      "name": "Tom"
    }
    
    GET test_index/_mapping
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    这里写图片描述

    可以看到在默认情况下,字符串被识别成为text类型,并且有一个子字段keyword。

    现在设置动态模板,要求匹配到string类型的字段设置为keyword:

    PUT test_index
    {
      "mappings": {
        "doc": {
          "dynamic_templates": [
            {
              "strings_as_keywords": {
                "match_mapping_type": "string",
                "mapping": {
                  "type": "keyword"
                }
              }
            }
          ] 
        }
      }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    重新创建文档并查看mapping: 
    这里写图片描述

    name字段的类型变成了 keyword类型

    字段匹配

    现在想将以message开头的字段且为string的匹配称为text类型,其余为keyword:

    PUT test_index
    {
      "mappings": {
        "doc": {
          "dynamic_templates": [
            {
              "message_as_text": {
                "match_mapping_type": "string",
                "match": "message",
                "mapping": {
                  "type": "text"
                }
              }
            },
            {
              "strings_as_keywords": {
                "match_mapping_type": "string",
                "mapping": {
                  "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

    Dynamic Templates 的匹配顺序是从上到下执行的,匹配到一个后后面的规则就会跳过

    然后创建一个文档并查看mapping:

    PUT test_index/doc/1
    {
      "name": "john",
      "message": "good boy"
    }
    
    GET test_index/_mapping
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    这里写图片描述

    可以看到message被设置为了text类型,name还是keyword

    double设定为float

    这里写图片描述

    这样可以节省空间

    自定义mapping的建议


    一般步骤

    自定义mapping 的步骤:

    1. 写一条文档到es的临时索引中,获取es自动生成的mapping
    2. 修改第一步得到的mapping,自定义相关配置
    3. 使用第2步的mapping创建市级的索引

    实际举例

    假设我得到了需要存入es的文档,首先将文档写入临时的index中:

    PUT test_index/doc/1
    {
      "referre": "-",
      "response_code": "200",
      "remote_ip": "172.0.0.1",
      "method": "POST",
      "username": "-",
      "http_version": "1.1",
      "body_sent": {
        "bytes": "0"
      },
      "url": "/helloworld"
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    然后查看es自动生成的mapping:

    GET test_index/_mapping
    • 1

    现在希望将bytes设置为整型,url设置为text类型,其他都使用keyword(将上一步的输出复制过来就好):

    PUT product_index
    {
        "mappings": {
          "doc": {
            "properties": {
              "body_sent": {
                "properties": {
                  "bytes": {
                    "type": "long"
                  }
                }
              },
              "http_version": {
                "type": "keyword"
              },
              "method": {
                "type": "keyword"
              },
              "referre": {
                "type": "keyword"
              },
              "remote_ip": {
                "type": "keyword"
              },
              "response_code": {
                "type": "keyword"
              },
              "url": {
                "type": "text"
              },
              "username": {
                "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

    这样直接将测试index的mapping复制过来进行修改,不会遗漏字段,修改完成设置一个index的名称就行了。

    然后就可以向实际的索引中写入文档了:

    PUT product_index/doc/1
    {
      "referre": "-",
      "response_code": "200",
      "remote_ip": "172.0.0.1",
      "method": "POST",
      "username": "-",
      "http_version": "1.1",
      "body_sent": {
        "bytes": "0"
      },
      "url": "/helloworld"
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    然后查看一下实际索引的mapping:

    GET product_index/_mapping
    • 1

    这里写图片描述

    使用动态模板优化

    上边的设置方法很直接,但是当字段比较多的时候显得复杂,可以使用动态模板进行匹配:

    DELETE product_index
    
    PUT product_index
    {
        "mappings": {
          "doc": {
            "dynamic_templates": [
              {
                "strings": {
                  "match_mapping_type": "string",
                  "mapping": {
                    "type": "keyword"
                  }
                }
              }
            ],
            "properties": {
              "body_sent": {
                "properties": {
                  "bytes": {
                    "type": "long"
                  }
                }
              },
              "url": {
                "type": "text"
              },
              "username": {
                "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

    这里使用动态模板匹配所有字符串都设置为keyword类型,需要单独设置类型的在下面另行指出。

    索引模板

    什么是索引模板

    索引模板,index template,主要用于在新建索引时自动应用预先设置的配置,简化索引创建的步骤。

    模板中可以设定索引的配置以及mapping,可以有多个模板,根据order设置,order大的覆盖小的范围。

    API

    这里写图片描述

    模板加载顺序根据 order 从小到大加载,后面的大order的模板的配置将会覆盖小 order配置。

    获取与删除的API 如下: 
    这里写图片描述

    举例

    这里设置了两个索引模板:

    PUT _template/test_template
    {
      "index_patterns": ["te*", "bar*"],
      "order": 0,
      "settings": {
        "number_of_shards": 1
      },
      "mappings": {
        "doc": {
          "_source": {
            "enabled": false
          },
          "properties": {
            "name": {
              "type": "keyword"
            }
          }
        }
      }
    }
    
    PUT _template/test_template2
    {
      "index_patterns": ["test*"],
      "order": 1,
      "settings": {
        "number_of_shards": 1
      },
      "mappings": {
        "doc": {
          "_source": {
            "enabled": true
          }
        }
      }
    }
    • 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

    然后先创建一个foo_index,并获取一下它的mapping:

    PUT foo_index
    GET foo_index/_mapping
    • 1
    • 2

    这里写图片描述

    因为这个index没有被任何一个模板匹配到,所以它的mapping是空的

    再创建一个bar_index,并获取一下它的mapping:

    PUT bar_index
    GET bar_index/_mapping
    • 1
    • 2

    这里写图片描述

    这个索引匹配到了test_template

    再创建一个test_index,并获取一下它的index配置:

    PUT test_index
    GET test_index/
    • 1
    • 2

    这里写图片描述

    这个索引匹配到了test_template2模板,这使得索引的”_source”: {“enabled”: true}

  • 相关阅读:
    关于 JAVA 中使用 Preferences 读写注册表时要注意的地方
    VS2010编译以前版本工程时 ERROR CVT1100:duplicate resource,type:MANIFEST解决办法
    在博客园安家了,同时献上刚汉化的 Code Snippet 插件!
    安装mariadb
    路飞学城部署方法
    配置supervisor工具
    使用uwsgi启动django项目
    nginx访问日志和压测命令
    nginx学习
    虚拟环境之virtualenvwrapper
  • 原文地址:https://www.cnblogs.com/bigben0123/p/10057121.html
Copyright © 2020-2023  润新知