--- title: "文档源缺失 (document_source_missing_exception) 错误排查与解决" date: 2026-02-20 lastmod: 2026-02-20 description: "document_source_missing_exception 表示文档存在但其源数据(_source)被禁用或丢失,通常由索引映射中禁用了 _source 引起。" tags: ["文档", "源数据", "映射配置"] summary: "为什么这个错误发生 # document_source_missing_exception 表示文档存在但其源数据(_source)被禁用或丢失。这通常发生在尝试获取或更新文档的 _source 字段时。 这个错误可能由以下原因引起: _source 被禁用:索引映射中禁用了 _source _source 被过滤:_source 被exclude 配置过滤掉了 文档损坏:文档的 _source 数据损坏 更新操作冲突:在 _source 被禁用的索引上执行需要 _source 的操作 版本升级问题:从旧版本升级后 _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." --- ## 为什么这个错误发生 `document_source_missing_exception` 表示文档存在但其源数据(_source)被禁用或丢失。这通常发生在尝试获取或更新文档的 _source 字段时。 这个错误可能由以下原因引起: 1. **_source 被禁用**:索引映射中禁用了 _source 2. **_source 被过滤**:_source 被exclude 配置过滤掉了 3. **文档损坏**:文档的 _source 数据损坏 4. **更新操作冲突**:在 _source 被禁用的索引上执行需要 _source 的操作 5. **版本升级问题**:从旧版本升级后 _source 数据丢失 ## 如何修复这个错误 ### 1. 检查索引映射 ```bash # 查看索引映射中的 _source 配置 GET //_mapping?pretty # 检查 _source 是否被禁用 GET //_mapping?filter_path=**._source ``` ### 2. 查看文档而不获取 _source ```bash # 使用 stored_fields 而不是 _source GET //_doc/?stored_fields= # 只返回文档元数据 GET //_doc/?_source=false ``` ### 3. 重新索引并启用 _source ```bash # 创建新索引并启用 _source PUT /-new { "mappings": { "_source": { "enabled": true }, "properties": { "field": { "type": "text" } } } } # 重新索引数据(注意:_source 丢失的数据无法恢复) POST /_reindex { "source": { "index": "" }, "dest": { "index": "-new" } } ``` ### 4. 使用 doc 而不是 _source 更新 ```bash # 在禁用 _source 的索引上,使用 doc 更新 POST //_update/ { "doc": { "field": "value" } } # 或使用 upsert POST //_update/ { "doc": { "field": "value" }, "doc_as_upsert": true } ``` ### 5. 检查 _source 过滤配置 ```bash # 检查是否配置了 exclude GET //_mapping?filter_path=**._source # 修改配置 PUT //_mapping { "_source": { "excludes": [] } } ``` ### 6. 使用 stored fields ```bash # 在映射中配置存储字段 PUT / { "mappings": { "_source": { "enabled": false }, "properties": { "title": { "type": "text", "store": true } } } } # 检索存储的字段 GET //_doc/?stored_fields=title ``` ### 7. 验证文档是否存在 ```bash # 检查文档是否存在 HEAD //_doc/ # 只获取元数据 GET //_doc/?_source=false ``` ### 8. 使用 script 进行更新 ```bash # 在某些情况下可以使用脚本更新 POST //_update/ { "script": { "source": "ctx._source.field = params.value", "lang": "painless" }, "params": { "value": "new_value" } } # 注意:如果 _source 被禁用,这会失败 ``` ### 9. 从副本或备份恢复 ```bash # 如果有副本或备份 # 恢复启用了 _source 的数据 # 从快照恢复 POST /_snapshot///_restore { "indices": "" } ``` ### 10. 修改映射(仅限新索引) ```bash # 注意:禁用 _source 后无法重新启用 # 需要创建新索引 PUT /-v2 { "mappings": { "_source": { "enabled": true, "excludes": ["sensitive_field"] } } } ``` ### 预防措施 - 尽量不要禁用 _source(除非确定不需要) - 如果要禁用 _source,考虑使用 store 存储关键字段 - 使用 excludes 而不是完全禁用 _source - 在设计索引时仔细考虑 _source 配置 - 定期备份索引数据 - 在测试环境验证 _source 配置后再应用到生产