如何在Elasticsearch输出插件的脚本函数中访问@metadata字段
解决Logstash Elasticsearch输出脚本中访问@metadata字段的问题
看起来你踩了两个常见的坑:一是默认情况下@metadata字段不会被传入Elasticsearch的脚本参数,二是直接用Logstash变量插值会触发ES的脚本编译限制。我来帮你搞定这个问题:
问题根源
- @metadata字段默认不传入脚本:Logstash的Elasticsearch输出插件在传递事件到ES脚本时,不会自动把
@metadata里的字段包含到params.event中,所以你用params.event.get("[@metadata][url]")只能拿到null。 - 变量插值触发编译错误:如果直接在脚本里用
%{[@metadata][url]},Logstash会为每个不同的URL生成新的脚本内容,ES会因为频繁编译新脚本触发too many dynamic script compilations错误。
正确解决方案:用script_params传递元数据字段
你需要通过script_params配置项,把需要的@metadata字段显式传递给ES脚本,这样脚本内容固定,参数动态变化,既不会有编译问题,又能正确拿到字段值。
修改后的完整配置如下:
output { elasticsearch { hosts => "***************" user => "****" index => "****" password => "*********" document_type => "document" document_id => "%{[@metadata][domain]}" action => "update" # 显式传递@metadata中的url到脚本参数 script_params => { "target_url" => "%{[@metadata][url]}" } # 优化后的脚本,直接引用params.target_url script => ' if (ctx._source.urls.length < 1001) { if (!ctx._source.urls.contains(params.target_url)) { ctx._source.urls.add(params.target_url); } } ' doc_as_upsert => true } }
关键改动说明
- 添加
script_params:把@metadata里的url字段赋值给脚本参数target_url,这样ES脚本就能直接通过params.target_url访问到这个值。 - 优化脚本逻辑:用ES的
contains方法替代手动循环判断URL是否存在,代码更简洁高效。 - 避免动态脚本编译:脚本内容完全固定,只有
params.target_url是动态变化的,ES只会编译一次脚本,不会触发编译限制。
另外,记得确保你的ES索引中urls字段是数组类型,否则contains和add操作会报错哦。
内容的提问来源于stack exchange,提问作者24x7
相关产品推荐
相关产品推荐

