@TOC


参考ES 7版本官方文档
官方7.17文档

挑了一些我觉得重要的点总结
如有谬误,欢迎指正


mapping是什么

在ES里创建一个索引

PUT demo_index
{
    "mappings": {
        "dynamic": false
        "properties": {
            "demo_id": {
                "type": "text"
            }
        }
    }
}

上面的properties里定义了字段demo_id,它的类型是text。dynamic选择了false说明mapping不需要动态规则来匹配,这种情况下进行搜索时和普通的关系型数据库搜索非常类似。

mapping类似于数据库中的表结构定义,定义以下这些内容

  • 定义字段名称
  • 定义字段数据类型
  • 字段、倒排索引的相关配置

但是和比如mysql这样的数据相比还是有很多不同之处,搜索的字段类型可以提前定义好,也可以不定义让ES来推测,也可在搜索的时候动态加入新字段。

GET /demo_index/_mapping

查看mapping

动态mapping

如果你想使用动态mapping就将上面提到的dynamic字段设置为true或者runtime

默认动态mapping

ES允许直接插入文档,不需要提前定义类型、字段 ,当你查询的时候会自动推测匹配显示出来。

curl -X PUT "localhost:9200/data/_doc/1?pretty" -H 'Content-Type: application/json' -d'
{ "count": 5 }
使用kibana的话直接PUT data/_doc/1 ... 就行

自动检测类型和添加字段就是动态mapping,ES有默认的检测规则,我们自己也可以定义自己的规则。

设计自己的mapping检测模板

这一块比较复杂

match_mapping_type
这个可以理解为根据字段默认检测出来的类型进行匹配

用的官方文档的案例:
可以看到当默认检测出来的字段类型为integer时,将替换为long类型;如果检测出来的类型为text或者keyword类型,将会替换为string类型。

PUT demo_index
{
  "mappings": {
    "dynamic_templates": [
      {
        "integers": {
          "match_mapping_type": "long",
          "mapping": {
            "type": "integer"
          }
        }
      },
      {
        "strings": {
          "match_mapping_type": "string",
          "mapping": {
            "type": "text",
            "fields": {
              "raw": {
                "type":  "keyword",
                "ignore_above": 256
              }
            }
          }
        }
      }
    ]
  }
}

这张图是在默认检测下,从Json解析出来的数据类型和ES里的数据的对应关系。需要注意的是dynamic字段设置为true和runtime的对应关系是略有不同的。
在这里插入图片描述

math/unmatch
根据字段名称去匹配字段类型
如下,如果JSON解析出来的字段匹配long_*并且不匹配*_text,并且默认检测出来的类型是long,那么将其匹配为string类型。

PUT demo-index
{
  "mappings": {
    "dynamic_templates": [
      {
        "longs_as_strings": {
          "match_mapping_type": "string",
          "match":   "long_*",
          "unmatch": "*_text",
          "mapping": {
            "type": "long"
          }
        }
      }
    ]
  }
}

除了使用简单的通配符来进行匹配之外,还可以使用正则表达式:

"match_pattern": "regex",
"match": "^profit_\d+$"

path_match/path_unmatch
这个是根据字段路径匹配,我理解是用于匹配多层级的对象。
这里产生的效果就是name对象去掉middle字段。

PUT demo-index
{
  "mappings": {
    "dynamic_templates": [
      {
        "full_name": {
          "path_match":   "name.*",
          "path_unmatch": "*.middle",
          "mapping": {
            "type":       "text",
            "copy_to":    "full_name"
          }
        }
      }
    ]
  }
}

PUT demo-index/_doc/1
{
  "name": {
    "first":  "John",
    "middle": "Winston",
    "last":   "Lennon"
  }
}
官方文档里的这个案例,还使用了copy_to,copy_to可以将值复制到另一个字段里,是一个很实用的功能。

运行时字段

可以在mapping下设置runtime部分,使用script脚本来控制动态字段。
脚本可以访问整个文档,包括原始_source和mapping字段,脚本会查询所有所需字段的值。

PUT demo-index/
{
  "mappings": {
    "runtime": {
      "day_of_week": {
        "type": "keyword",
        "script": {
          "source": "emit(doc['@timestamp'].value.dayOfWeekEnum.getDisplayName(TextStyle.FULL, Locale.ROOT))"
        }
      }
    },
    "properties": {
      "@timestamp": {"type": "date"}
    }
  }
}

运行时字段在搜索时不会出现在_source里,但是会有这个field,搜索时可以指定这个字段将其值搜索出来

>GET demo-index/_search
{
  "fields" : ["day_of_week"],
  "query": {
    "match": {
      ...
    }
  }
}

动态值就会显示在查询结果的hits里的每个hit的fields里

在某些情况下这个功能可以省去reindex, 比如发现mapping里某字段希望修改它的数据类型,或者希望某些字段可以有另外的一种形式,在mapping中不太方便修改,方案可以有进行reindex,但是也可以通过这种动态形式拿到想获取的值(读时建模)。


当设置dynamic字段为runtime时,

PUT demo-index
{
  "mappings": {
    "dynamic": "runtime",
    "properties": {
      "@timestamp": {
        "type": "date"
      }
    }
  }
}

检测到的新字段会自动加入到mapping的fields作为运行时字段。


也可以随时更新或删除运行时字段。要替换现有的运行时字段,在具有相同名称的映射中添加一个新的运行时字段。设置null就可以删除。

PUT demo-index/_mapping
{
 "runtime": {
   "day_of_week": null
 }
}

dynamic

dynamic用于控制是否动态添加新字段,可选项有:

  • true:新字段添加到mapping中(默认)。
  • runtime:新字段作为运行时字段添加到mapping中,这些字段不可索引,是_source在查询时加载的。
  • false:忽略新字段,这些字段不会被索引或搜索,但仍会出现在_source返回的命令和字段中。这些字段不会添加到mapping中,必须显式添加新字段。
  • strict:如果检测到新字段,则会抛出异常。必须将新字段显式添加到mapping中。

动态模式 (true)通俗来说就是往index里写入doc,doc里的字段类型对应es里的什么数据类型,将会由默认推测规则来进行自动推测匹配(当然也可以自义定推测规则)。

不需要动态模式(false)的时候,可以按照自己的实际需求去设置mapping,插入doc的时候,字段与mapping里的保持一致,如果doc添加了一个mapping里不存在的字段,新字段不会被自动添加到mapping中,并且指定该字段进行查询时,也无法匹配到结果,可以存储、但是不能索引。

当dynamic设置为false时,显式设置mapping,类似于关系型数据库

fhzmWJ
21 声望0 粉丝