ElasticSearch7.3 学习之定制动态映射(dynamic mapping)
1、dynamic mapping
ElasticSearch中有一个非常重要的特性——动态映射,即索引文档前不需要创建索引、类型等信息,在索引的同时会自动完成索引、类型、映射的创建。
当ES在文档中碰到一个以前没见过的字段时,它会利用动态映射(dynamic mapping)来决定该字段的类型,并自动地对该字段添加映射。
有时这正是需要的行为,但有时不是,需要留意。你或许不知道在以后你的文档中会添加哪些字段,但是你想要它们能够被自动地索引。或许你只是想要忽略它们。或者,尤其当你将ES当做主要的数据存储使用时,大概你会希望这些未知的字段会抛出异常来提醒你注意这一问题。
幸运的是,你可以通过dynamic设置来控制这一行为,它能够接受以下的选项:
true:默认值。动态添加字段false:新检测到的字段将被忽略。这些字段将不会被索引,因此将无法搜索,但仍将出现在返回点击的源字段中。这些字段不会添加到映射中,必须显式添加新字段。strict:如果碰到陌生字段,抛出异常
dynamic设置可以适用在根对象上或者object类型的任意字段上。你应该默认地将dynamic设置为strict,但是为某个特定的内部对象启用它:
创建mapping
PUT /my_index
{
"mappings": {
"dynamic": "strict",
"properties": {
"title": {
"type": "text"
},
"address": {
"type": "object",
"dynamic": "true"
}
}
}
插入数据
PUT /my_index/_doc/1
{
"title": "my article",
"content": "this is my article",
"address": {
"province": "guangdong",
"city": "guangzhou"
}
}
报错,原因为content为新增字段。会抛出异常
{
"error": {
"root_cause": [
{
"type": "strict_dynamic_mapping_exception",
"reason": "mapping set to strict, dynamic introduction of [content] within [_doc] is not allowed"
}
],
"type": "strict_dynamic_mapping_exception",
"reason": "mapping set to strict, dynamic introduction of [content] within [_doc] is not allowed"
},
"status": 400
}
2、自定义 dynamic mapping策略
2.1 数据类型
如果你知道你需要动态的添加的新字段,那么你也许会启用动态映射。然而有时动态映射的规则又有些不够灵活。幸运的是,你可以调整某些设置来让动态映射的规则更加适合你的数据。
es会根据传入的值,推断类型,具体如下表所示。
|
JSON data type |
Elasticsearch data type |
ES中的数据类型 |
|
|
No field is added. |
不会添加字段 |
|
|
|
boolean |
|
floating point number |
|
double |
|
integer |
|
long |
|
object |
|
object |
|
array |
Depends on the first non- |
依赖于第一个非null得值 |
|
string |
Either a |
如果通过了date检测,则为date 如果通过了numeric检测,则为Number |
2.2 date_detection 日期探测
默认会按照一定格式识别date,比如yyyy-MM-dd。但是如果某个field先过来一个2017-01-01的值,就会被自动dynamic mapping成date,后面如果再来一个"hello world"之类的值,就会报错。可以手动关闭某个type的date_detection,如果有需要,自己手动指定某个field为date类型。
首先删除上面新建的索引
DELETE my_index
然后下面的语句代表的含义为:日期探测为false,表示可添加不是date数据类型的字段,也不会被推断成date类型。address字段里面为true,代表可动态往里面添加新的字段。
PUT /my_index
{
"mappings": {
"date_detection": false,
"properties": {
"title": {
"type": "text"
},
"address": {
"type": "object",
"dynamic": "true"
}
}
}
}
测试插入数据。下面的语句代表最外层级新增content、post_date两个字段,address层级新增province、city字段。
PUT /my_index/_doc/1
{
"title": "my article",
"content": "this is my article",
"address": {
"province": "guangdong",
"city": "guangzhou"
},
"post_date": "2019-09-10"
}
查看映射
GET /my_index/_mapping
返回,可以看到字段都成功新增,日期检测(date_detection)为false,所以post_date字段类型不是date类型。
{
"my_index" : {
"mappings" : {
"date_detection" : false,
"properties" : {
"address" : {
"dynamic" : "true",
"properties" : {
"city" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"province" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
}
}
},
"content" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"post_date" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"title" : {
"type" : "text"
}
}
}
}
}
下面为自定义日期格式语法,读者可自行试验。
PUT my_index
{
"mappings": {
"dynamic_date_formats": ["MM/dd/yyyy"]
}
}
插入数据
PUT my_index/_doc/1
{
"create_date": "09/25/2019"
}
2.3 numeric_detection 数字探测
虽然json支持浮点和整数数据类型,但某些应用程序或语言有时可能需要将数字呈现为字符串。通常正确的解决方案是显式地映射这些字段,但是可以启用数字检测(默认情况下禁用)来自动完成这些操作。
首先删除上面新建的索引
DELETE my_index
然后开启数字检测
PUT my_index
{
"mappings": {
"numeric_detection": true
}
}
插入数据
PUT my_index/_doc/1
{
"my_float": "1.0",
"my_integer": "1"
}
查看映射
GET my_index/_mapping
返回
{
"my_index" : {
"mappings" : {
"numeric_detection" : true,
"properties" : {
"my_float" : {
"type" : "float"
},
"my_integer" : {
"type" : "long"
}
}
}
}
}
可以看到两个字段被映射为浮点类型了。
3、定制dynamic mapping template
通过dynamic_templates,你可以拥有对新字段的动态映射规则拥有完全的控制。你设置可以根据字段名称或者类型来使用一个不同的映射规则。
每个模板都有一个名字,可以用来描述这个模板做了什么。同时它有一个mapping用来指定具体的映射信息,和至少一个参数(比如match)用来规定对于什么字段需要使用该模板。
首先删除上面新建的索引
DELETE my_index
运行下面的语句,代表的含义为:匹配以_en结尾并且是string类型的字段,设置它的type为text,使用english分词。
PUT /my_index
{
"mappings": {
"dynamic_templates": [
{
"en": {
"match": "*_en",
"match_mapping_type": "string",
"mapping": {
"type": "text",
"analyzer": "english"
}
}
}
]
}
}
插入数据
PUT /my_index/_doc/1
{
"title": "this is my first article"
}
PUT /my_index/_doc/2
{
"title_en": "this is my first article"
}
查看映射
GET my_index/_mapping
返回,可以看到title_en字段采用english分词器,说明模板生效了。
{
"my_index" : {
"mappings" : {
"dynamic_templates" : [
{
"en" : {
"match" : "*_en",
"match_mapping_type" : "string",
"mapping" : {
"analyzer" : "english",
"type" : "text"
}
}
}
],
"properties" : {
"title" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"title_en" : {
"type" : "text",
"analyzer" : "english"
}
}
}
}
}
搜索
GET my_index/_search?q=first
GET my_index/_search?q=is
title字段没有匹配到任何的dynamic模板,默认就是standard分词器,不会过滤停用词,is会进入倒排索引,用is来搜索是可以搜索到的
title_en字段匹配到了dynamic模板,就是english分词器,会过滤停用词,is这种停用词就会被过滤掉,用is来搜索就搜索不到了
4、模板写法
下面给出了一些大概的写法,读者可根据自身实际需求自定义模板
PUT my_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
}
}
}
}
}
]
}
}
模板参数:匹配满足的字段、不匹配满足的字段、匹配的数据类型、路径匹配、路径不匹配。
"match": "long_*",
"unmatch": "*_text",
"match_mapping_type": "string",
"path_match": "name.*",
"path_unmatch": "*.middle",
"match_pattern": "regex",
"match": "^profit_\d+$"
5、应用场景
5.1 结构化搜索
默认情况下,elasticsearch将字符串字段映射为带有子关键字(keyword)字段的文本字段。但是,如果只对结构化内容进行索引,而对全文搜索不感兴趣,则可以仅将“字段”映射为“关键字”。但是请注意,这意味着为了搜索这些字段,必须搜索索引所用的完全相同的值。
{
"strings_as_keywords": {
"match_mapping_type": "string",
"mapping": {
"type": "keyword"
}
}
}
5.2 仅搜索
与前面的示例相反,如果您只关心字符串字段的全文搜索,并且不打算对字符串字段运行聚合、排序或精确搜索,您可以将其仅映射为文本字段(这是es5之前的默认行为)
{
"strings_as_text": {
"match_mapping_type": "string",
"mapping": {
"type": "text"
}
}
}
5.3 norms 不关心评分
当计算得分的时候,是否需要把字段长度用作参数计算。
尽管计算得分时把字段长度考虑在内可以提高得分的精确性,但这样会消耗大量的磁盘空间(每个文档的每个字段都会消耗一个字节,即使某些文档不包含这个字段)。因此,如果不需要计算字段的得分,你应该禁用该字段的norms。特别是这个字段仅用于聚合或者过滤。
{
"properties": {
"title": {
"type": "text",
"norms": false
}
}
}
ElasticSearch7.3 学习之定制动态映射(dynamic mapping)的更多相关文章
- ES 12 - 配置使用Elasticsearch的动态映射 (dynamic mapping)
目录 1 动态映射(dynamic mapping) 1.1 什么是动态映射 1.2 体验动态映射 1.3 搜索结果不一致的原因分析 2 开启dynamic mapping策略 2.1 约束策略 2. ...
- 聊聊elasticsearch7.8的模板和动态映射
最近想写一篇es的索引的一个设计,由于设计的东西特别多,当然,elasticsearch的模板和动态映射也是其中的一个设计点,所以干脆先来聊聊索引的模板和动态映射,模板,听这个名字就相当于一些公共可用 ...
- ElasticSearch7.3 学习之定制分词器(Analyzer)
1.默认的分词器 关于分词器,前面的博客已经有介绍了,链接:ElasticSearch7.3 学习之倒排索引揭秘及初识分词器(Analyzer).这里就只介绍默认的分词器standard analyz ...
- ElasticSearch7.3 学习之Mapping核心数据类型及dynamic mapping
1.mapping的核心数据类型以及dynamic mapping 1.1 核心的数据类型 string :text and keyword,byte,short,integer,long,float ...
- 2018/2/13 ElasticSearch学习笔记三 自动映射以及创建自动映射模版,ElasticSearch聚合查询
终于把这些命令全敲了一遍,话说ELK技术栈L和K我今天花了一下午全部搞定,学完后还都是花式玩那种...E却学了四天(当然主要是因为之前上班一直没时间学,还有安装服务时出现的各种error真是让我扎心了 ...
- 使用Logstash创建ES映射模版并进行数据默认的动态映射规则
本文配置为 ELK 即(Elasticsearch.Logstash.Kibana)5.5.1. Elasticsearch 能够自动检测字段的类型并进行映射,例如引号内的字段映射为 String,不 ...
- Asp.Net SignalR 使用记录 技术回炉重造-总纲 动态类型dynamic转换为特定类型T的方案 通过对象方法获取委托_C#反射获取委托_ .net core入门-跨域访问配置
Asp.Net SignalR 使用记录 工作上遇到一个推送消息的功能的实现.本着面向百度编程的思想.网上百度了一大堆.主要的实现方式是原生的WebSocket,和SignalR,再次写一个关于A ...
- Java的动态代理(dynamic proxy)
什么是动态代理(dynamic proxy) 动态代理(以下称代理),利用Java的反射技术(Java Reflection),在运行时创建一个实现某些给定接口的新类(也称“动态代理类”)及其实例(对 ...
- ASP.NET路由系统实现原理:HttpHandler的动态映射
我们知道一个请求最终通过一个具体的HttpHandler进行处理,而我们熟悉的用于表示一个Web页面的Page对象就是一个HttpHandler,被用于处理基于某个.aspx文件的请求.我们可以通过H ...
随机推荐
- 聊一聊Redis事务
没错,Redis也有事务管理,但是功能很简单,在正式开发中也并不推荐使用.但是面试中有可能会问到,所以本文简单谈一谈Redis的事务. 通过这篇文章,你会了解 Redis为什么要提供事务? Redis ...
- 基于XC7Z100+AD9361的双收双发无线电射频板卡
一.板卡概述 板卡基于Xilinx公司的SoC架构(ARM+FPGA)的ZYNQ7100芯片和ADI公司高集成度的捷变射频收发器AD9361,实现频谱范围70MHz~6GHz,模拟带宽200KHz~5 ...
- 暑假撸系统7- 熊孩子的捣乱!javascript保存前台状态!
系统大体框架已经搭的差不多了, 往下就是技术性的美化以及修补了,但这也是最最耗费时间的.在这个过程就发现了一个有意思的需求,这里把思路以及解决方案总结下. 因为做的是考试系统,不管是大或者小的考试,本 ...
- 使用docker部署canal
文章目录 mysql开启binlog mysql创建canal用户 启动canal容器 配置canal 启动canal容器 查看docker容器日志 canal-client 验证 关于canal m ...
- set和setenv
今天用set设置PATH变量(加一个路径),发现虽然echo的时候显示修改成功了,实际执行命令的时候确没有去那个路径查找:当前shell是c shell(csh). 在网上找了一些材料,总结如下: ...
- Java邮件发送中的setRecipient方法使用
一.方法setRecipient(Message.RecipientType type, Address address),是用于设置邮件的接收者. 1.有两个参数,第一个参数是接收者的类型,第二 ...
- RFC2889广播时延测试——网络测试仪实操
一.简介 RFC 2889为LAN交换设备的基准测试提供了方法学,它将RFC 2544中为网络互联设备基准测试所定义的方法学扩展到了交换设备,提供了交换机转发性能(Forwarding Perform ...
- Docker遇到的一些问题和感想
Docker 是"不可变"架构. 当你希望改变一个服务的时候(比如更新版本.修改配置.开放端口),不允许直接登录到服务器上改变某个文件,而是应该把这个服务整个删掉,然后替换成新的版 ...
- 【C#表达式树 一】Expressions 命名空间 38个类 2个接口 3个枚举
注解 抽象类 Expression 提供用于为表达式树建模的类层次结构的根. 此命名空间中派生自的类 Expression (例如 MemberExpression 和 ParameterExpres ...
- Glob 语法及解析
Glob 语法及解析 目录 1. glob 简介 2. glob 语法 3. .gitignore 4. Python glob 1 glob 简介 glob 是用于匹配符合指定模式的文件集合的一种语 ...