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

为什么这个错误发生 #

document_source_missing_exception 表示文档存在但其源数据(_source)被禁用或丢失。这通常发生在尝试获取或更新文档的 _source 字段时。

这个错误可能由以下原因引起:

  1. _source 被禁用:索引映射中禁用了 _source
  2. _source 被过滤:_source 被exclude 配置过滤掉了
  3. 文档损坏:文档的 _source 数据损坏
  4. 更新操作冲突:在 _source 被禁用的索引上执行需要 _source 的操作
  5. 版本升级问题:从旧版本升级后 _source 数据丢失

如何修复这个错误 #

1. 检查索引映射 #

# 查看索引映射中的 _source 配置
GET /<index>/_mapping?pretty

# 检查 _source 是否被禁用
GET /<index>/_mapping?filter_path=**._source

2. 查看文档而不获取 _source #

# 使用 stored_fields 而不是 _source
GET /<index>/_doc/<id>?stored_fields=<field_name>

# 只返回文档元数据
GET /<index>/_doc/<id>?_source=false

3. 重新索引并启用 _source #

# 创建新索引并启用 _source
PUT /<index>-new
{
  "mappings": {
    "_source": {
      "enabled": true
    },
    "properties": {
      "field": { "type": "text" }
    }
  }
}

# 重新索引数据(注意:_source 丢失的数据无法恢复)
POST /_reindex
{
  "source": { "index": "<index>" },
  "dest": { "index": "<index>-new" }
}

4. 使用 doc 而不是 _source 更新 #

# 在禁用 _source 的索引上,使用 doc 更新
POST /<index>/_update/<id>
{
  "doc": {
    "field": "value"
  }
}

# 或使用 upsert
POST /<index>/_update/<id>
{
  "doc": {
    "field": "value"
  },
  "doc_as_upsert": true
}

5. 检查 _source 过滤配置 #

# 检查是否配置了 exclude
GET /<index>/_mapping?filter_path=**._source

# 修改配置
PUT /<index>/_mapping
{
  "_source": {
    "excludes": []
  }
}

6. 使用 stored fields #

# 在映射中配置存储字段
PUT /<index>
{
  "mappings": {
    "_source": { "enabled": false },
    "properties": {
      "title": {
        "type": "text",
        "store": true
      }
    }
  }
}

# 检索存储的字段
GET /<index>/_doc/<id>?stored_fields=title

7. 验证文档是否存在 #

# 检查文档是否存在
HEAD /<index>/_doc/<id>

# 只获取元数据
GET /<index>/_doc/<id>?_source=false

8. 使用 script 进行更新 #

# 在某些情况下可以使用脚本更新
POST /<index>/_update/<id>
{
  "script": {
    "source": "ctx._source.field = params.value",
    "lang": "painless"
  },
  "params": {
    "value": "new_value"
  }
}

# 注意:如果 _source 被禁用,这会失败

9. 从副本或备份恢复 #

# 如果有副本或备份
# 恢复启用了 _source 的数据

# 从快照恢复
POST /_snapshot/<repository>/<snapshot>/_restore
{
  "indices": "<index>"
}

10. 修改映射(仅限新索引) #

# 注意:禁用 _source 后无法重新启用
# 需要创建新索引

PUT /<index>-v2
{
  "mappings": {
    "_source": {
      "enabled": true,
      "excludes": ["sensitive_field"]
    }
  }
}

预防措施 #

  • 尽量不要禁用 _source(除非确定不需要)
  • 如果要禁用 _source,考虑使用 store 存储关键字段
  • 使用 excludes 而不是完全禁用 _source
  • 在设计索引时仔细考虑 _source 配置
  • 定期备份索引数据
  • 在测试环境验证 _source 配置后再应用到生产