Elasticsearch重索引时如何用Painless脚本将新增字段设为keyword类型
解决方法
你需要提前控制新增字段的映射类型,才能稳定使用newfield.keyword进行访问,以下是两种可行操作方案:
方案1:提前定义目标索引Mapping(最推荐)
该方案可控性最高,完全避免Elasticsearch自动推断类型出错:
- 第一步:先创建目标索引,显式指定
newfield的字段结构,原有字段的映射可以直接从源索引复制后补充进去即可:
PUT 你的目标索引名 { "mappings": { "properties": { // 此处可补充原有字段的mapping配置 "newfield": { "type": "text", // 如果你不需要对该字段做全文检索,可以直接删除text相关配置,只保留keyword类型定义 "fields": { "keyword": { "type": "keyword", "ignore_above": 256 } } } } } }
- 第二步:补全后执行你的重索引脚本即可:
POST _reindex { "source": { "index": "你的源索引名" }, "dest": { "index": "你的目标索引名" }, "script": { "source": "ctx._source.newfield = 'test'", "lang": "painless" } }
方案2:配置动态模板适配
如果你不想提前手动创建目标索引,可以通过动态模板规则,让所有新增字符串字段默认生成keyword子字段(Elasticsearch默认动态规则其实已经包含该逻辑,如果你之前修改过动态映射才需要额外配置):
PUT 你的目标索引名/_mapping { "dynamic_templates": [ { "auto_add_keyword": { "match_mapping_type": "string", "mapping": { "type": "text", "fields": { "keyword": { "type": "keyword", "ignore_above": 256 } } } } } ] }
配置完成后再执行重索引操作即可。
额外优化说明
如果你不需要对newfield做全文检索,仅需要精确匹配、聚合、排序能力,可以直接把newfield的类型定义为纯keyword,不需要上层的text类型,既节省存储空间也能提升查询效率,这种场景下直接访问newfield即可,不需要加.keyword后缀。
内容的提问来源于stack exchange,提问作者eze
相关产品推荐
相关产品推荐

