📣 极限科技诚招搜索运维工程师(Elasticsearch/Easysearch)- 全职/北京 👉 : 立即申请加入

配置项作用 #

indices.id_field_data.enabled 配置项用于控制是否允许在文档的 _id 字段上加载 fielddata(字段数据)

当启用时,可以对 _id 字段进行排序和聚合操作;禁用后会阻止在 _id 字段上的 fielddata 访问。

配置项属性 #

  • 配置路径: indices.id_field_data.enabled
  • 数据类型: Boolean(布尔值)
  • 默认值: true
  • 是否可选: 是
  • 作用域: NodeScope(节点级别)
  • 动态更新: 是(支持动态更新)
  • 弃用状态: ⚠️ 此功能已被标记为弃用

配置项详解 #

工作机制 #

_id 字段 fielddata 访问

enabled = true (默认):

查询包含 _id 排序
    │
    ↓
加载 _id 字段的 fielddata ✅
    │
    ↓
执行排序操作
    │
    ↓
返回结果


enabled = false:

查询包含 _id 排序
    │
    ↓
尝试加载 fielddata ❌
    │
    ↓
抛出异常:
"Fielddata access on the _id field is disallowed,
 you can re-enable it by updating the dynamic
 cluster setting:
 indices.id_field_data.enabled"

弃用说明 #

弃用背景

_id 字段 fielddata 已被弃用的原因:

1. 内存开销
   - fielddata 加载需要额外内存
   - _id 字段对所有查询都存在
   - 大量查询会累积内存消耗

2. 性能影响
   - 加载 fielddata 有性能开销
   - 影响 JVM 堆内存使用

3. 更好的替代方案
   - 将 _id 值复制到文档字段
   - 使用 doc_values 而不是 fielddata
   - 性能更好,内存使用更可控

替代方案 #

推荐的替代实现

旧方式 (已弃用):
{
  "_id": "doc123",
  "_source": {
    "title": "Example"
  }
}

对 _id 排序: 需要 fielddata ❌


新方式 (推荐):
{
  "_id": "doc123",
  "_source": {
    "title": "Example",
    "id_field": "doc123"  # 复制 _id 值
  },
  "id_field": {
    "type": "keyword",
    "doc_values": true
  }
}

对 id_field 排序: 使用 doc_values ✅

配置建议 #

⚠️ 重要提示 #

此配置项已被标记为弃用,建议使用替代方案。

保持启用(默认) #

indices:
  id_field_data:
    enabled: true  # 默认值

建议: 仅在旧代码迁移期间使用。新项目应使用替代方案。

禁用 fielddata #

indices:
  id_field_data:
    enabled: false  # 禁用

建议: 新项目应该禁用,使用替代方案。

代码示例 #

easysearch.yml 基础配置 #

indices:
  id_field_data:
    enabled: true

禁用配置 #

indices:
  id_field_data:
    enabled: false

动态更新配置 #

PUT /_cluster/settings
{
  "transient": {
    "indices.id_field_data.enabled": false
  }
}

推荐的替代实现 #

PUT /my_index
{
  "mappings": {
    "properties": {
      "id_field": {
        "type": "keyword",
        "doc_values": true
      }
    }
  }
}
POST /my_index/_doc
{
  "title": "Example",
  "id_field": "doc123"
}

使用场景 #

推荐禁用的场景 #

  • 新项目: 所有新项目应该禁用
  • 性能优化: 希望减少内存使用
  • 最佳实践: 遵循官方推荐的替代方案

临时保持启用的场景 #

  • 旧代码迁移: 正在从旧代码迁移
  • 兼容性需要: 需要与旧版本兼容
  • 测试验证: 测试环境中验证功能

性能影响分析 #

内存使用对比

使用 fielddata:

查询 1: 加载 _id fielddata
   内存: +10MB

查询 2: 加载 _id fielddata
   内存: +10MB

查询 3: 加载 _id fielddata
   内存: +10MB

总内存: 30MB ❌


使用 doc_values:

索引时: 写入 doc_values
   内存: +5MB (一次性)

查询 1, 2, 3: 读取 doc_values
   内存: 几乎无增加 ✅

总内存: 约 5MB

弃用迁移 #

从 fielddata 迁移到 doc_values

步骤 1: 添加新字段

PUT /_template/template_name
{
  "mappings": {
    "properties": {
      "id_field": {
        "type": "keyword",
        "doc_values": true
      }
    }
  }
}

步骤 2: 修改索引代码

// 旧代码
.sort("_id")

// 新代码
.sort("id_field")

步骤 3: 更新数据

POST /_update_by_query
{
  "query": { "match_all": {} },
  "script": {
    "source": "ctx._source.id_field = ctx._id"
  }
}

步骤 4: 验证功能

测试新字段功能
确认排序和聚合正常
禁用 fielddata

错误处理 #


禁用 fielddata 后的错误

错误信息:
"Fielddata access on the _id field is disallowed"

原因:
1. 配置 enabled = false
2. 查询尝试访问 _id 的 fielddata

解决方案:
方案 1: 使用替代字段
   - 使用 id_field 字段代替
   - 确保索引映射正确

方案 2: 启用配置(不推荐)
   - 临时启用 id_field_data.enabled
   - 长期应该迁移到替代方案

方案 3: 修改查询逻辑
   - 移除对 _id 的排序/聚合
   - 使用其他字段

注意事项 #

  1. 已弃用: 此功能已被标记为弃用,不应在新代码中使用。

  2. 默认启用: 默认值为 true,保持向后兼容。

  3. 替代方案: 官方推荐使用 doc_values 替代。

  4. 动态更新: 支持动态更新,修改后立即生效。

  5. 内存考虑: 禁用可以减少内存使用。

  6. 性能影响: doc_values 性能比 fielddata 更好。

  7. 规划迁移: 建议规划迁移到替代方案。

  8. 索引映射: 替代字段需要添加到索引映射中。

  9. 数据更新: 需要更新现有文档以包含替代字段。

  10. 测试验证: 迁移后需要测试所有相关功能。