更新文档,_source 字段必须为 true 吗
在 Elasticsearch 中,_source
字段并不必须为 true
,但它的设置会直接影响更新操作的行为。以下是关键解析和实际影响:
1._source 字段的作用
_source
是文档的原始 JSON 数据存储,默认值为true
(即存储原始数据)。- 如果
_source
被禁用(false
),Elasticsearch 不会保存文档的原始内容,仅存储倒排索引用于搜索。
2.更新操作与 _source 的关系
✅ 情况 1:_source 为 true(默认)
- 支持所有更新方式:
- 部分更新(
POST /index/_update/{id}
) - 脚本更新(
ctx._source.field
) _update_by_query
- 部分更新(
- 原因:更新时需要读取原始文档内容,修改后再重新索引。
❌ 情况 2:_source 为 false
- 仅支持以下更新:
- 完全替换(
PUT /index/_doc/{id}
):直接覆盖整个文档,无需原始内容。 - 删除后重新插入。
- 完全替换(
- 禁止以下操作:
- 部分更新(报错
"reason": "source disabled"
) - 脚本更新(依赖
ctx._source
)
- 部分更新(报错
3.实际案例验证
步骤 1:创建索引(禁用 _source)
PUT /test_no_source
{
"mappings": {
"_source": {
"enabled": false
},
"properties": {
"name": {
"type": "text"
},
"count": {
"type": "integer"
}
}
}
}
注意,下面的写法是错误的。
PUT /test_no_source
{
"mappings": {
"_source": false, // 禁用 _source
"properties": {
"name": { "type": "text" },
"count": { "type": "integer" }
}
}
}
步骤 2:插入测试数据
POST /test_no_source/_doc/101
{
"name": "张三",
"count": 5
}
步骤 3:尝试部分更新(失败)
POST /test_no_source/_update/101
{
"doc": {
"count": 2
}
}
响应报错:
步骤 4:完全替换(成功)
PUT /test_no_source/_doc/101
{
"name": "test",
"count": 2 // 直接覆盖整个文档
}
4.如何检查索引的 _source 设置
GET /your_index/_mapping
查看返回结果中是否包含 "_source": { "enabled": false }
。
5.生产环境建议
- 保持
_source
为true
(默认值),除非:- 明确不需要更新功能。
- 对存储空间极度敏感(禁用
_source
能节省磁盘,但牺牲灵活性)。
- 禁用后的补救措施(不是万能的!):
- 重建索引并启用
_source
:PUT /new_index { "mappings": { "_source": true, "properties": { ... } } }
- 使用
_reindex
API 迁移数据。
- 重建索引并启用
6.总结
_source 状态 | 支持部分更新 | 支持脚本更新 | 存储开销 | 适用场景 |
---|---|---|---|---|
true (默认) | ✅ | ✅ | 较高 | 需要灵活更新的常规场景 |
false | ❌ | ❌ | 较低 | 只读日志/归档数据 |
⭐ 非常重要:如果业务中需要更新文档,务必保持
_source
启用!另外,一定谨慎禁用_source
!!!