如何在Kibana中对字段执行算术运算?我的查询为何无结果?
嘿,你写的那个查询语句其实是不正确的,原因很简单——Elasticsearch的常规查询语法(比如你用的这种query string方式)并不支持直接在条件里进行字段间的算术运算对比。你写的dataThroughput.totalPackets.value != 20 - dataThroughput.lostPackets.value,Elasticsearch会把右边的20 - dataThroughput.lostPackets.value当成一个普通的字符串去匹配,而不是计算它的数值结果,自然得不到你想要的筛选效果。
那该怎么正确实现totalPackets != C - lostPackets的筛选呢?这里给你两种可行的方案:
方案一:使用脚本查询(Script Query)
你可以借助Elasticsearch的Painless脚本,在查询中直接编写算术逻辑来对比字段值。比如用bool查询的must_not来排除满足等式的文档,剩下的就是符合你要求的结果:
{ "query": { "bool": { "must_not": [ { "script": { "script": { "source": "doc['dataThroughput.totalPackets.value'].value == params.C - doc['dataThroughput.lostPackets.value'].value", "params": { "C": 20 // 这里可以替换成你需要的可变常量 } } } } ] } } }
注意事项:
- 确保
dataThroughput.totalPackets.value和dataThroughput.lostPackets.value都是数值类型(比如long、integer),否则脚本会报错。 - 如果部分文档可能缺失这两个字段,可以在脚本里加个存在性判断,避免报错:
doc.containsKey('dataThroughput.totalPackets.value') && doc.containsKey('dataThroughput.lostPackets.value') && doc['dataThroughput.totalPackets.value'].value == params.C - doc['dataThroughput.lostPackets.value'].value
方案二:借助Runtime Field(适合Kibana可视化场景)
如果你是在Kibana里做可视化时需要这个筛选,可以先定义一个Runtime Field,提前计算出C - lostPackets的值,之后直接用这个字段和totalPackets做不等对比:
- 打开Kibana的索引模式设置,找到你的目标索引
- 添加一个新的Runtime Field,类型选数值型
- 输入Painless脚本:
def c = 20; // 替换为你的常量C if (doc.containsKey('dataThroughput.lostPackets.value')) { emit(c - doc['dataThroughput.lostPackets.value'].value); } else { emit(null); } - 保存这个字段(比如命名为
calculatedExpectedPackets)
之后在Kibana的筛选或可视化配置中,直接设置dataThroughput.totalPackets.value != calculatedExpectedPackets即可。
额外建议:
如果这个筛选逻辑是你经常要用的,且数据量较大,脚本查询的性能可能会不如常规字段查询。这种情况下,你可以在写入数据时就提前计算好C - lostPackets的值并存储为一个新字段,这样后续查询会更高效。
内容的提问来源于stack exchange,提问作者Keselme

