如何将自定义字段设为Elasticsearch文档ID?配置遇问题
首先得明确:你提到的在Elasticsearch mapping里用_id.path指定自定义字段作为文档ID的方式,确实在Elasticsearch 7.x及以后的版本中已经被完全废弃了,所以你之前的mapping配置才会触发mapper_parsing_exception,这个是正常的,现在官方推荐的做法就是通过写入客户端(比如Logstash)来指定document_id。
至于你说Logstash配置了document_id => "%{mini_system_key}"但没生效,大概率是配置细节或者字段处理出了问题,我给你一步步排查和解决的方案:
1. 先确认字段在Logstash中是否存在
Logstash的document_id是通过字段引用的,所以首先要确保mini_system_key这个字段在到达output阶段时是存在的:
- 可以在filter阶段加一段调试代码,打印这个字段的值,验证是否能正确获取:
filter { ruby { code => 'puts "当前事件的mini_system_key值:#{event.get("mini_system_key")}"' } }
启动Logstash后,看控制台输出,如果能看到mini_system_key的具体值,说明字段没问题;如果输出nil或者空,那就是上游的输入/过滤阶段把这个字段弄丢了,得检查input或者filter的配置,确保字段被正确保留。
2. 检查字段名的拼写和路径
- 字段名是大小写敏感的!比如你的数据里是
Mini_System_Key但你写的是mini_system_key,就会引用失败,导致生成随机ID。 - 如果
mini_system_key是嵌套在某个对象里的字段(比如来自JSON的data.mini_system_key),那得用完整的路径引用:document_id => "%{[data][mini_system_key]}"
3. 正确的Logstash Output配置示例
给你一个标准的配置模板,确保没有遗漏关键项:
output { elasticsearch { hosts => ["http://your-es-host:9200"] # 替换成你的ES地址 index => "your-target-index" # 替换成你的目标索引名 document_id => "%{mini_system_key}" # 这里直接引用字段 # 如果ES开启了认证,加上下面两行 # user => "your-es-username" # password => "your-es-password" } # 可以加stdout输出,方便调试 stdout { codec => rubydebug } }
4. 处理字段为空的情况
如果mini_system_key存在空值或者null,Logstash会自动生成随机的document_id,这时候你可以在filter阶段处理:
- 直接丢弃空值事件:
filter { if [mini_system_key] == "" or [mini_system_key].nil? { drop {} } }
- 或者给空值设置默认ID(比如用时间戳):
filter { if [mini_system_key] == "" or [mini_system_key].nil? { mutate { add_field => { "mini_system_key" => "default-id-%{+YYYYMMddHHmmssSSS}" } } } }
5. 验证是否生效
数据写入后,你可以在Elasticsearch的Dev Tools里执行查询,验证文档ID是否和mini_system_key一致:
GET your-target-index/_search { "query": { "term": { "mini_system_key": "某个已知的key值" } } }
查看返回结果里的_id字段,应该和mini_system_key的值完全相同。
内容的提问来源于stack exchange,提问作者Gibbs

