Es索引文档全量更新与迁移

需求背景

es索引需新增字段,该字段初始值由某个旧字段确定。数据量大概1000w条文档。

两种方案:

1、直接使用update_by_query命令进行全量更新。

2、新建索引并进行全量迁移,迁移时更新新增字段的初始值。

经过测试,方案1的耗时较长(2小时左右),方案2耗时20分钟左右,所以采用方案2进行处理。

新建索引

新建目标索引

java 复制代码
PUT /tbproj_1211
{
  "settings": {
    "index": {
      "number_of_shards": 1,
      "number_of_replicas": 1,
      "analysis" : {
        "normalizer" : {
          "CustomNormalizer" : {
            "filter" : [
              "lowercase",
              "asciifolding"
            ],
            "type" : "custom"
          }
        },
        "analyzer" : {
          "optimizeIK" : {
            "type" : "custom",
            "tokenizer" : "ik_max_word"
          }
        }
      }
    }
  },
  "mappings": {
    "dynamic" : "true",
    "properties" : {
      "createTime" : {
        "type" : "long",
        "coerce" : false
      },
      "creator" : {
        "type" : "keyword"
      },
      "credit" : {
        "type" : "keyword"
      },
      "dbId" : {
        "type" : "keyword"
      },
      "definition" : {
        "type" : "keyword"
      },
      "fileName" : {
        "type" : "keyword"
      },
      "fromDbId" : {
        "type" : "keyword"
      },
      "id" : {
        "type" : "keyword"
      },
      "isApproved" : {
        "type" : "keyword"
      },
      "modifiedTime" : {
        "type" : "long",
        "coerce" : false
      },
      "modifier" : {
        "type" : "keyword"
      },
      "note" : {
        "type" : "keyword"
      },
      "original" : {
        "type" : "text",
        "fields" : {
          "keyword" : {
            "type" : "keyword"
          },
          "normalizer" : {
            "type" : "keyword",
            "normalizer" : "CustomNormalizer"
          },
          "pattern" : {
            "type" : "text",
            "norms" : false,
            "analyzer" : "pattern"
          },
          "standard" : {
            "type" : "text",
            "norms" : false,
            "analyzer" : "standard"
          }
        },
        "norms" : false,
        "analyzer" : "optimizeIK"
      },
      "originalLang" : {
        "type" : "keyword"
      },
      "remark" : {
        "type" : "keyword"
      },
      "reviewTime" : {
        "type" : "long",
        "coerce" : false
      },
      "reviewer" : {
        "type" : "keyword"
      },
      "translation" : {
        "type" : "text",
        "fields" : {
          "keyword" : {
            "type" : "keyword"
          },
          "normalizer" : {
            "type" : "keyword",
            "normalizer" : "CustomNormalizer"
          },
          "pattern" : {
            "type" : "text",
            "norms" : false,
            "analyzer" : "pattern"
          },
          "standard" : {
            "type" : "text",
            "norms" : false,
            "analyzer" : "standard"
          }
        },
        "norms" : false,
        "analyzer" : "optimizeIK"
      },
      "translationLang" : {
        "type" : "keyword"
      }
    }
  }
}

迁移数据

由于数据量较大,采用全量迁移和增量迁移。全量迁移在凌晨执行,增量迁移可在发版时执行。

全量迁移

迁移脚本

java 复制代码
### 全量迁移
POST _reindex?wait_for_completion=false
{
  "conflicts": "proceed",
  "source": {
    "index": "tbproj",
    "size":10000
  },
  "dest": {
    "index": "tbproj_1211",
    "op_type": "index"
  },
  "script": {
    "lang": "painless",
    "params": {
      "lv1_terms": ["", "译员术语"],
      "lv2_terms": ["PM术语"],
      "lv3_terms": ["客户术语", "行业术语"]
    },
    "source": """
      // 处理字段不存在的情况
      if (!ctx._source.containsKey('remark')) {
        ctx._source.credit = 2;
        return;
      }
      
      def remark = ctx._source.remark;
      
      // 处理 null 值
      if (remark == null) {
        ctx._source.credit = 2;
        return;
      }
      
      String remarkStr = remark.toString();
      
      if (params.lv1_terms.contains(remarkStr)) {
        ctx._source.credit = 2;
      } else if (params.lv2_terms.contains(remarkStr)) {
        ctx._source.credit = 3;
      } else if (params.lv3_terms.contains(remarkStr)) {
        ctx._source.credit = 4;
      } else {
        ctx._source.credit = 2;
      }
    """
  }
}

执行上述命令后,会返回任务id,可根据返回的任务id查询迁移的进度。

java 复制代码
GET _tasks/ouuGEmiVSOaw2ih49hGepg:13942427

增量迁移

执行完全量迁移脚本后,可使用下方脚本继续迁移增量数据(在执行全量迁移命令后产生的数据)。

java 复制代码
### 增量迁移
POST _reindex?wait_for_completion=false
{
  "conflicts": "proceed", ###出现冲突时,继续迁移
  "source": {
    "index": "tbproj",
    "size":10000,
    "query": {
      "range": {
        "modifiedTime": {
          "gte": 1764910963831  ###执行全量迁移操作的时间
        }
      }
    }
  },
  "dest": {
    "index": "tbproj_1211",
    "op_type": "index"  ###出现冲突时,覆盖已有数据
  },
  "script": {
    "lang": "painless",
    "params": {
      "lv1_terms": ["", "译员术语"],
      "lv2_terms": ["PM术语"],
      "lv3_terms": ["客户术语", "行业术语"]
    },
    "source": """
      // 处理字段不存在的情况
      if (!ctx._source.containsKey('remark')) {
        ctx._source.credit = 2;
        return;
      }
      
      def remark = ctx._source.remark;
      
      // 处理 null 值
      if (remark == null) {
        ctx._source.credit = 2;
        return;
      }
      
      String remarkStr = remark.toString();
      
      if (params.lv1_terms.contains(remarkStr)) {
        ctx._source.credit = 2;
      } else if (params.lv2_terms.contains(remarkStr)) {
        ctx._source.credit = 3;
      } else if (params.lv3_terms.contains(remarkStr)) {
        ctx._source.credit = 4;
      } else {
        ctx._source.credit = 2;
      }
    """
  }
}

删除索引

迁移完成后,校验数据完整性,校验通过后可删除旧索引(如果不需要新索引名称与旧索引名称一致,可不用删除)

java 复制代码
DELETE /tbproj

创建别名

旧索引删除后,可为新索引创建和旧索引名称一致的别名,后续就可以继续使用旧索引名称进行相关操作。

java 复制代码
###查看已有别名
GET /tbproj_1211/_alias
###创建或删除别名
POST _aliases
{
  "actions": [
    {
      "add": { ###创建别名
        "index": "tb_1211",
        "alias": "tb"
      }
    },
    {
      "add": {
        "index": "tbproj_1211",
        "alias": "tbproj"
      }
    },
    {
      "remove": { ###删除别名
        "index": "tbproj_1211",
        "alias": "tbproj_01"
      }
    }
  ]
}
相关推荐
小羊没烦恼!6 天前
微服务化的基石——持续集成
java·大数据·word·powerpoint·.net
一隅论数智6 天前
给AI一张“业务概念地图“:本体如何从哲学走向企业智能
大数据·人工智能·经验分享·笔记·学习·学习方法·政务
LaughingZhu6 天前
Product Hunt 每日热榜 | 2026-09-19
人工智能·深度学习·神经网络·搜索引擎·百度
尧炎科技6 天前
防潮抗变形,就选纯品梅花全桉多层板
大数据
程序员大阳6 天前
副队长大数据教程(5)--集群情况下虚拟机网络配置
大数据·集群·nat·网路
自由能燃气设备6 天前
商用全预混低氮冷凝锅炉免费方案vs付费方案对比+选型避坑指南
大数据·数据库·人工智能
科创致远6 天前
科创致远 ESOP 系统核心效能与实战价值展示
大数据·数据库·人工智能·精益工程
嘉立创FPC苗工6 天前
FPC与机器人的双向赋能,解锁智能装备进化新势能
大数据·人工智能·制造·fpc·电路板
AI职业加油站6 天前
AI智能体应用工程师证书:政策红利下的职业新风口
大数据·运维·人工智能·学习·职场发展
龙亘川6 天前
一网统管AI平台民生业务实践:基于城市数字底座赋能公积金业务服务升级
大数据·安全·智慧城市·开源软件·数据可视化·政务