如何阻止 Logstash 在 Elasticsearch 中自动创建默认映射?
控制 Elasticsearch 字段映射可预建索引、配置索引模板或由 Logstash 安装模板;未知字段仍受 dynamic 设置控制,显式 mapping 不会自动关闭动态映射。
根本办法:在 Logstash 写数据之前,先在 Elasticsearch 中预建索引(或索引模板)并定义好 mappings——已定义字段沿用映射,但未定义的新字段仍可能动态添加。也可以在 Logstash 的 elasticsearch output 中用 template 参数指定自定义模板。
方法一:预建索引 + 显式 mapping
curl -X PUT "localhost:9200/my-logs" -H 'Content-Type: application/json' -d '{
"mappings": {
"properties": {
"timestamp": { "type": "date" },
"level": { "type": "keyword" },
"message": { "type": "text" },
"response_time": { "type": "float" }
}
}
}'
索引已存在且带映射后,Logstash 写入时沿用现有映射,仍会按 dynamic 设置处理未知字段,显式 properties 不会自动关闭动态映射。
方法二:索引模板(推荐用于按日期滚动的索引)
索引名带日期(app-logs-2024.01.15)每天新建,预建不现实,用索引模板:
curl -X PUT "localhost:9200/_index_template/app-logs-template" -H 'Content-Type: application/json' -d '{
"index_patterns": ["app-logs-*"],
"template": {
"mappings": {
"properties": {
"timestamp": { "type": "date" },
"message": { "type": "text" }
}
}
}
}'
匹配 app-logs-* 的新索引可套用该模板;有多个可组合模板匹配时需核对 priority 和模拟结果,不能假定本模板一定获选。
方法三:Logstash output 指定模板
output {
elasticsearch {
hosts => ["http://localhost:9200"]
index => "app-logs-%{+YYYY.MM.dd}"
template => "/path/to/my-template.json"
template_api => "composable" # 对应上面的_index_template格式,需插件版本支持
template_name => "app-logs"
template_overwrite => true
}
}
为什么要在意
ES 自动推断的映射经常不符合预期:字符串默认映射为 text+keyword 双字段、数字字符串仅在启用 numeric_detection 等对应配置时可能识别成数字(默认关闭)、日期格式识别失败等。已有字段类型通常不能直接更改,需要新索引并重建数据;添加字段或部分可更新参数不一定重建,模板修改也不会自动重处理旧文档。
常见问题(FAQ)
Q:已经建错的索引怎么修?
A:mapping 不能原地修改字段类型。需要新建带正确映射的索引,然后 reindex 迁移数据,最后切换别名。
Q:如何查看现有索引的 mapping?
A:curl localhost:9200/my-index/_mapping。
Q:动态 mapping 能彻底关掉吗?
A:可以,在 mappings 对象中设 "dynamic": "strict"(未知字段写入报错)或 "dynamic": false(未知字段通常保留在 _source,但不建立可搜索映射)。strict 要覆盖实际完整事件字段,包括 Logstash 的 @timestamp 等。manage_template=false 只禁用插件安装模板,不关闭 Elasticsearch dynamic mapping。