对已有数据重建 ES 字段索引

重建 ES 字段索引,对已有数据生效。

方案 1:添加 multi-field mapping(推荐)

步骤 1:更新 mapping

PUT your_index/_mapping
{
  "properties": {
    "sendTime": {
      "type": "text",
      "fields": {
        "keyword": {
          "type": "keyword",
          "ignore_above": 256
        }
      }
    }
  }
}

步骤 2:重建索引使 mapping 生效

POST your_index/_update_by_query?refresh=true
{
  "query": {
    "match_all": {}
  }
}

方案 2:零停机时间的安全做法

步骤 1:创建新索引模板

PUT _index_template/your_template
{
  "index_patterns": ["your_index_pattern*"],
  "template": {
    "mappings": {
      "properties": {
        "sendTime": {
          "type": "text",
          "fields": {
            "keyword": {
              "type": "keyword",
              "ignore_above": 256
            }
          }
        }
      }
    }
  }
}

步骤 2:滚动更新(如果使用日期索引)

新的数据会自动应用新 mapping,旧数据保持不变。

验证方法

更新后验证是否生效:

GET your_index/_mapping/field/sendTime

应该看到:

{
  "your_index": {
    "mappings": {
      "sendTime": {
        "full_name": "sendTime",
        "mapping": {
          "sendTime": {
            "type": "text",
            "fields": {
              "keyword": {
                "type": "keyword",
                "ignore_above": 256
              }
            }
          }
        }
      }
    }
  }
}

在 Java 代码中使用

// 更新mapping后,可以这样排序
SortBuilder sortBuilder;
try {
    sortBuilder = SortBuilders.fieldSort("sendTime.keyword").order(SortOrder.DESC);
} catch (Exception e) {
    // 兜底方案
    sortBuilder = SortBuilders.fieldSort("_id").order(SortOrder.ASC);
    log.warn("sendTime.keyword字段不可用,使用_id排序");
}

注意事项

  1. 已有数据:需要_update_by_query 才能生效
  2. 性能影响:重建过程中可能影响查询性能
  3. 存储增加:keyword 字段会额外占用存储空间
  4. 建议时机:在业务低峰期执行

最安全的方案:先在测试环境验证,确认无问题后再在生产环境执行。