第四阶段 33 · index / mapping 管理(建索引、别名、reindex)

33 · index / mapping 管理(建索引、别名、reindex)

阶段:第四阶段 / 写入与索引管理

ES:建索引 / mapping / 别名 / reindex | PostgreSQL:DDL、CREATE TABLE、视图、表重建


1. 概念

索引管理相当于数据库的 DDL:

ES 操作 SQL 对照
PUT /index + mapping CREATE TABLE + 列定义
别名 alias 视图 / 可切换的表名
reindex INSERT INTO new SELECT * FROM old(表重建)
PUT /index/_mapping ALTER TABLE ADD COLUMN

本项目建索引入口:InsertToEsTask.createIndex → CreateSalesIndexHandler,

mapping 从 mappings/*.json(如 salesdata_idx.json)读取。


2. PostgreSQL 对照

sql 复制代码
CREATE TABLE salesdata (
  invoice_number varchar,
  net_amount     numeric,
  invoice_dt     date
);

-- 加列(ES 只能加不能改类型)
ALTER TABLE salesdata ADD COLUMN customer_group varchar;

-- 视图切换(类比别名)
CREATE VIEW salesdata_current AS SELECT * FROM salesdata_v2;

3. ES DSL

复制代码
# 建索引 + settings + mapping
PUT salesdata_idx
{
  "settings": { "number_of_shards": 3, "number_of_replicas": 1 },
  "mappings": {
    "properties": {
      "invoice_number": { "type": "keyword" },
      "net_amount":     { "type": "double" },
      "invoice_dt":     { "type": "date", "format": "yyyy-MM-dd" }
    }
  }
}

# 追加字段(不能改已有字段类型)
PUT salesdata_idx/_mapping
{ "properties": { "customer_group": { "type": "keyword" } } }

# 别名切换(原子)
POST _aliases
{
  "actions": [
    { "remove": { "index": "salesdata_v1", "alias": "salesdata" } },
    { "add":    { "index": "salesdata_v2", "alias": "salesdata" } }
  ]
}

# reindex:老索引数据搬到新索引
POST _reindex
{ "source": { "index": "salesdata_v1" }, "dest": { "index": "salesdata_v2" } }

4. Spring Boot 实现

java 复制代码
@Component
public class Doc33IndexAdmin {

    @Autowired
    private ElasticsearchClient elasticsearchClient;

    /** 建索引 + mapping(简化版,本项目实际读 mappings/*.json) */
    public void createIndex(String indexName) throws IOException {
        boolean exists = elasticsearchClient.indices()
                .exists(e -> e.index(indexName)).value();
        if (exists) {
            return;
        }
        elasticsearchClient.indices().create(c -> c
                .index(indexName)
                .settings(st -> st.numberOfShards("3").numberOfReplicas("1"))
                .mappings(m -> m
                        .properties("invoice_number", p -> p.keyword(k -> k))
                        .properties("net_amount", p -> p.double_(d -> d))
                        .properties("invoice_dt", p -> p.date(d -> d.format("yyyy-MM-dd")))));
    }

    /** 追加字段:类比 ALTER TABLE ADD COLUMN */
    public void addKeywordField(String indexName, String field) throws IOException {
        elasticsearchClient.indices().putMapping(m -> m
                .index(indexName)
                .properties(field, p -> p.keyword(k -> k)));
    }

    /** 原子切换别名 */
    public void switchAlias(String alias, String oldIndex, String newIndex) throws IOException {
        elasticsearchClient.indices().updateAliases(a -> a
                .actions(ac -> ac.remove(r -> r.index(oldIndex).alias(alias)))
                .actions(ac -> ac.add(ad -> ad.index(newIndex).alias(alias))));
    }
}

与本项目对照:建索引逻辑见 CreateSalesIndexHandler,mapping 新增字段时

参考 ADD_FIELD_SKILL 里 ES 部分(在 mapping 的 properties 追加字段)。


5. 坑与最佳实践

  1. mapping 不可改已有字段类型:改类型只能新建索引 + reindex + 切别名。
  2. 用别名解耦 :应用只认别名(如 salesdata),底层索引版本切换对上层透明、零停机。
  3. 动态映射风险:生产索引建议显式 mapping,或关掉动态映射,避免字段类型被自动猜错。
  4. 分片数建后不可改 :number_of_shards 定死,需重新规划只能 reindex;副本数可动态调。
  5. reindex 期间双写或停写:保证新老索引数据一致,切别名前校验文档数。

阶段小结

第四阶段完成后,你应该能:单文档增删改、bulk 批量写、按条件批量更新/删除、

建索引与 mapping、用别名做零停机切换、用 reindex 重建索引。

相关推荐
合尘猫6 分钟前
AI客服国标落地一个月:从工程角度看,真正要改的是三处数据结构
数据库·人工智能·架构
Maynor9961 小时前
免费 Cloudflare 只有 10 个 D1?满了之后的「穷鬼打法」:表前缀复用同一个库
数据库·后端·云计算·cloudflare
冰暮流星1 小时前
mysql之索引设计的原则
数据库·mysql·1024程序员节
昵称画9 小时前
交接班记录电子化:三班之间的信息不漏
开发语言·数据库·人工智能·低代码·php
缓慢更新10 小时前
审批的加签与会签:多人意见怎么合
android·java·数据库·低代码·rxjava
跨境联盟11 小时前
大健康实体如何搭建产品差异化:对比普通营养品与合规跨境膳食补充剂服务模式
数据库·ai·健康医疗·健康管理·精准营养
有想法的py工程师11 小时前
PostgreSQL EXPLAIN中的Cost模型分析(random_page_cost参数):优化器眼中的代价世界与执行计划生成
数据库·postgresql
前进的李工11 小时前
飞书企业知识库设计+后端高频八股
数据库·redis·后端·mysql·性能优化·飞书·rag
泡海椒12 小时前
JQuick-SQL CSV 文件数据接入:转换为内存表后再查询
数据库·sql
为思念酝酿的痛13 小时前
MySQL数据类型
数据库·mysql