首页 > 其他分享 >Elasticsearch Mapping类型修改

Elasticsearch Mapping类型修改

时间:2024-08-09 16:16:33浏览次数:12  
标签:users 索引 Mapping mapping 修改 Elasticsearch user type id

背景

通常数据库进行分库分表后,目前比较常规的作法,是通过将数据异构到Elasticsearch来提供分页列表查询服务;在创建Elasticsearch索引时,基本都是会参考目前的业务需求、关系数据库中的类型以及对数据的相关规划来定义相关字段mapping的类型.
在Elasticsearch的mapping中的列(或则叫属性),有几个比较重要的参数(更多参数参考官方文档)

  • 列类型:type

    指定了该列的数据类型,常用的有text, keyword, date, long, double,boolean以及 objectnested,不同的类型也有对应的不同查询方式,创建之后是不能修改的;

  • 是否可索引:index

    index选项控制字段值是否被索引。它接受true or false,并且默认为true. 未索引的字段不可查询,当然也不能做为排序字段。

但是在实际的开发过程中,又会有需求对现有的mapping的type进行修改(类似对MySQL数据表的字段进行DDL操作)的诉求。比如商品上的价格price字段,按原来的业务分析,只需要提供数据返回即可,在创建索引时类型定义了keyword了,并且index设置成了false,这时我们需要根据价格的范围查询或则进行排序操作,就希望对mapping进行调整,将类型修改成数字类型,索引也需要加上;今天针对Elasticsearch的Mapping类型进行修改,讨论几个可行的方案

方案1:运用reindex

遇到问题第一时间,我们应该是查询官方文档是否有相关的操作说明,在官方文档中,确实还能找到对已有mapping更新的相关api put-mapping,通过这个文档,很快可以找到文档中对修改已有mapping的列的方式(参考官方文档),同时也提到的通过 reindex的方式来修改已有类型的方式;

除了支持的mapping parameters外,您不能更改现有字段的映射或字段类型。更改现有字段可能会使已编制索引的数据无效。如果您需要更改字段的映射,请使用正确的映射创建一个新索引并将您的数据重新索引reindex到该索引中。

如原来索引的mapping如下

PUT /users
{
  "mappings" : {
    "properties": {
      "user_id": {
        "type": "long"
      }
    }
  }
}

//加一了两条数据
POST /users/_doc?refresh=wait_for
{
    "user_id" : 12345
}

POST /users/_doc?refresh=wait_for
{
    "user_id" : 12346
}

这时想修改user_id的类型为keyword,我们直接是修改不了的。

//尝试直接修改type,行不通,会报错
PUT /users/_mapping
{
    "properties": {
        "user_id": {
            "type": "keyword"
        }
    }
}

//报错信息
{
  "error": {
    "root_cause": [
      {
        "type": "illegal_argument_exception",
        "reason": "mapper [user_id] of different type, current_type [long], merged_type [keyword]"
      }
    ],
    "type": "illegal_argument_exception",
    "reason": "mapper [user_id] of different type, current_type [long], merged_type [keyword]"
  },
  "status": 400
}

按官方文档说的reindex重新索引可按以下步骤操作

操作步骤

第一步:创建新的索引 new_usersuser_id的类型定义成 keyword

PUT /new_users
{
  "mappings" : {
    "properties": {
      "user_id": {
        "type": "keyword"
      }
    }
  }
}

第二步:将原user索引标记为只读

控制我们的应用系统,数据停写不再向老索引中写数据,并且最好对老索引进行只读操作设置,保证在reindex的过程中,不要生产新数据,导致新老索数据不一致;

//设置索引为读写的
PUT /users/_settings
{
  "settings": {
    "index.blocks.write": true
  }
}

第三步:将原user索引中的数据迁移到new_users

POST /_reindex
{
  "source": {
    "index": "users"
  },
  "dest": {
    "index": "new_users"
  }
}

reindex还有很多的参数可以配置,包括从远程的一个集群迁移数据都是可以的,详细可参考:Reindex API

如果新的索引的mapping的定义与原索引的定义有差异的,会按新索引定义的 dynamic 规则进行数据的迁移,具体的,可以参考: dynamic

dynamic设置控制是否可以动态添加新字段。它接受三种设置:

说明
true 新检测到的字段被添加到映射中。(默认); 新增的数据类型的规则,可以参考:dynamic-mapping
false 忽略新检测到的字段。这些字段不会被编入索引,因此将无法搜索,但仍会出现在_source返回的命中字段中。这些字段不会添加到映射中,必须明确添加新字段。
strict 如果检测到新字段,则会抛出异常并拒绝文档。必须将新字段显式添加到映射中。

同时将原user索引标记为可读写

//设置索引为可读写
PUT /users/_settings
{
  "settings": {
    "index.blocks.write": false
  }
}

第四步:切换到使用新的mapping

  1. 可以将应用系统中的配置改成新索引

  2. 也可以通过索引的别名的方式为新索引增加原来老索引的别名来操作,为索引增加别名参考文档:Add index alias API,在增加别名前,需要删除原来的老索引;

//为索引增加别名 基本格式
PUT /<index>/_alias/<alias>
POST /<index>/_alias/<alias>

//为new_users索引增加别名users
PUT /new_users/_alias/users

//没有删除老索引前,是增加不了别名的,需要先删除老别名
{
  "error": {
    "root_cause": [
      {
        "type": "invalid_alias_name_exception",
        "reason": "Invalid alias name [users], an index exists with the same name as the alias",
        "index_uuid": "8Rbq_32BTHC4CoO_CqWdXA",
        "index": "users"
      }
    ],
    "type": "invalid_alias_name_exception",
    "reason": "Invalid alias name [users], an index exists with the same name as the alias",
    "index_uuid": "8Rbq_32BTHC4CoO_CqWdXA",
    "index": "users"
  },
  "status": 400
}

方案优劣分析

【优点】操作简单,官方方案

该方案,不需要对原索引做操作,在线即可进行,并且操作步骤也简单;也是官方文档提供的方案。

【缺点】数据量大迁移耗时长

当数据最大时,这个数据迁移会比较耗时

结论

当数据量小时,并且希望mapping比较规整好看,该方案是比较推荐的。当数据量大时,可能该方案在数据迁移过程中会比较耗时,需要评估是否可行;

方案2:运用multi-fields

为不同的目的以不同的方式索引同一个字段通常很有用。这就是multi-fields的目的。例如,一个string 字段可以映射为text用于全文搜索的字段,也可以映射keyword为用于排序或聚合的字段;
在这个方案中,应用的是mapping参数fields来对同一个列,定义多种数据类型;详细[【官方文档】multi-fields] (https://www.elastic.co/guide/en/elasticsearch/reference/7.5/multi-fields.html)

操作步骤

第一步:为列增加fields属性

还是以上面的users这个索引为例,我们还是想将user_id的类型定义成 keyword

PUT /users/_mapping
{
    "properties":{
        "user_id":{
            "type":"long",
            "fields":{
                "raw":{
                    "type":"keyword"
                }
            }
        }
    }
}

操作完成后,在usersuser_id列下,就会多出一个raw的子属性;在我们正常写数据user_id时,会自动生成这两个索引,一个是long类型的user_id,以及keyword类型的user_id.raw(注意这里有个点,跟子对象访问方式一样);
在put mapping时,type参数必需给,并且需要跟原来的类型一致,fields中新定义的子属性可以多个;

【可选】第二步:历史数据更新

针对历史数据需要处理,可以借助_update_by_query 来更新数据,只需要将原来的索引再写一次,即可将新加的字段写入数据。

POST /users/_update_by_query 

{
   "query":{
       "exists":{
           "field":"user_id"
       }
   },
   "script":{
       "source":"ctx._source.user_id=ctx._source.user_id ",
       "lang":"painless"
   }
}

// query 部分为需要更新数据过滤条件,可根据业务规则写
// script 更数据的逻辑,这个基本可以不改

方案优劣分析

【优点】不影响原索引,同一列可以定义多种类型

通过这方式不会影响原来的索引数据,可以不用修改现在的应用程序的读写方式,对应用程序一切按原来逻辑执行,对应用方无感知,非常优化。只需要有使用新类型的场景使用即可,可以说影响是最小的;
同时只是做了一个定义,执行速度是非常快的,对Elasticsearch服务基本不会有太大影响;并且对于同一个列可以定义多个类型,比如商品名称,在多国多语言环境下可以根据不同语言定义多个列,对应使用不同的分词器;

【缺点】老数据不会自动创建子索引,多出额外的存储

老数据不会自动创建索引,因为需要多出新的索引来,会增加额外的存储;

结论

1、需要对多一列创建多个索引类型时,是一个非常推荐的方案;
2、对于新索引,只有新业务使用,对老数据没有诉求的,也非常推荐该方案;

方案3:运用copy_to

copy_to是将多个字段的值,合并到一个字段中,便于搜索。但是也可以实现一个字段存在多个类型的需求。详细参考【官方文档】copy_to

操作步骤

还是用上面的users这个索引为例,为user_id创建一个copy列: user_id_raw 类型定义成 keyword

PUT /users/_mapping
{
    "properties":{
        "user_id_raw":{
          "type":"keyword",
          "copy_to":"user_id"
        }
    }
}

这个方案与方案2:multi-fields 基本是一样的,只是创建列的方式不同,优缺点都一样;

参考资料

标签:users,索引,Mapping,mapping,修改,Elasticsearch,user,type,id
From: https://www.cnblogs.com/Jcloud/p/18350936

相关文章

  • 数据库安全-ElasticSearch漏洞复现
    CVE-2014-3120命令执行漏洞一、漏洞详情老版本ElasticSearch支持传入动态脚本(MVEL)来执行一些复杂的操作,而MVEL可执行Java代码,而且没有沙盒,所以我们可以直接执行任意代码。MVEL执行命令代码:importjava.io.*;newjava.util.Scanner(Runtime.getRuntime().exec("whoami").getIn......
  • AD20如何批量修改丝印的大小
    选择想修改的元器件丝印,右击以下鼠标,出现如下界面在ObjectSpecifics里面选择Designgnator,将Any选项选择为same然后再右侧修改丝印的高和宽,一般将高选择为10mil,宽选择为2个mil。PS:一般推荐字宽/字高尺寸为2/10mil、4/25mil、5/30mil、6/45mil。......
  • 关联单据和处理前序单据的修改
    在系统设计中,关联单据和处理前序单据的修改是两个关键问题。这里是一些常见的做法和最佳实践:1. 单据关联使用ID关联:唯一标识符:为每个单据分配一个唯一的ID(通常是主键),用以唯一标识单据并在系统中进行引用。外键关系:在需要关联的单据中,使用外键字段来存储其他单据的ID。例如,采......
  • 注册表修改鼠标右键菜单
    文件/文件夹右键菜单:HKEY_CLASSES_ROOT*\shellHKEY_CLASSES_ROOT\Directory\shellHKEY_CLASSES_ROOT\Folder\shell驱动器右键菜单:HKEY_CLASSES_ROOT\Drive\shell桌面右键菜单:HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer\NoDesktop......
  • 深入浅出Java RestClient与Elasticsearch:一次简单的聚合查询实现
    文章目录一、什么是聚合查询?二、开始编写代码三、代码解析四、总结在当今的大数据时代,Elasticsearch作为一个分布式搜索和分析引擎,被广泛应用于各类数据密集型应用中。而使用Java与Elasticsearch交互进行数据操作时,JavaHighLevelRestClient提供了一种方便且......
  • MySQL:修改数据库密码及开启外部访问数据库
    修改数据库密码cd到数据库bin路径下mysql.exe-uroot-p登录成功ALTERUSER'root'@'localhost'IDENTIFIEDBY'123456';再打开一个cmd重新登陆mysql.exe-uroot-p登录成功开启外部访问数据库回到上层路径找到my.ini将内容bind-address行注释掉或者改成0.0.0.0......
  • android13 下拉栏修改为圆形图标
    在android13默认使用了我们想要将他改成圆形的图标,然后将字体修改到图标下方首先我们要找到图标是在哪里添加进去的在QSFactoryImpl有个方法@OverridepublicQSTileViewcreateTileView(Contextcontext,QSTiletile,booleancollapsedView){QSI......
  • R语言读取和修改 fcs文件
    记住要从上往下一个一个包的安装,已经安装了的就不用安装,如果就是读取和修改fcs文件,只需要安装flowCore包就可以了。if(!requireNamespace("BiocManager",quietly=TRUE))install.packages("BiocManager")##数据源:BiocManager::install("flowWorkspaceData")##数据......
  • php: 操作elasticsearch的别名
    一,添加别名1,代码://初始化es的client$client=$this->_init_es();//确定参数$params=['index'=>'gs_second',//索引名字'name'=>'gs_second_idx',//索引的别名......
  • elasticsearch: 指定索引数据的保存目录
    一,查看节点的fs得到索引数据的保存目录说明:修改索引数据的保存目录,通常是因为要把数据单独保存到服务器专用的数据盘,方便扩展\管理\备份等访问:http://localhost:9200/_nodes/stats/fs 也可以从命令行访问:[root@lhdpcelasticsearch]#curl-XGET"localhost:9200/_no......