Solr 7.2.1:基于分面结果求小时平均最大值的实现问询
为什么会报错?
你遇到的avgMyVal不是已知字段错误,是因为你在顶层分面里用max(avgMyVal)时,把avgMyVal当成了Solr索引中实际存在的字段,但实际上它只是你在tempi这个小时分面桶内计算出来的子聚合结果——Solr的同级分面之间是不能互相引用结果的,所以它识别不了这个“虚拟”的avgMyVal。
Solr 7.2.1支持这个需求吗?
当然支持!只是你的写法不符合Solr JSON分面的规则,需要调整实现方式,不需要额外配置(只要myTime是日期类型、myVal是数值类型,且都正确配置了索引属性就行)。
两种可行的解决方案
方案1:用Streaming Expressions在Solr端完成全计算
Solr的Streaming Expressions专门用来处理这种需要对聚合结果再做二次计算的场景,你可以通过以下表达式直接得到最终的最大值:
search(你的集合名, q="*:*", facet={ tempi:{ type:range, field:myTime, start:"NOW-7DAYS", end:"NOW", gap:"+1HOUR", facet:{avgMyVal:"avg(myVal)"} } } ) -> select(fl="tempi.buckets.avgMyVal") -> flatten() -> stats(avgMyVal='max(avgMyVal)')
这个表达式的逻辑是:先执行分面得到每个小时的平均值,然后提取所有平均值,将数组扁平化,最后对这些值求最大值。
方案2:客户端二次处理(更简单易上手)
如果不想用Streaming Expressions,你可以保留原来的分面查询(只去掉顶层的maxAvgMyVal部分):
json.facet={ tempi: { type: range, field: myTime, start: "NOW-7DAYS", end: "NOW", gap: "+1HOUR", facet: { avgMyVal: "avg(myVal)" } } }
拿到返回结果后,在你的客户端代码里遍历tempi.buckets数组,提取每个桶的avgMyVal值,然后找出其中的最大值即可。这种方式不需要学习Streaming Expressions,适合快速实现需求。
注意事项
- 确保
myTime字段在Solr schema中被定义为date类型,否则range分面无法按小时正确分组。 myVal字段需要是int、float、double等数值类型,这样avg()聚合才能正常计算。
内容的提问来源于stack exchange,提问作者Davide
相关产品推荐
相关产品推荐

