Esper技术问询:每3秒从最近两个事件中随机返回一个的实现问题
解决Esper每3秒从最近两个事件随机返回一个的问题
嘿,这个问题我之前也碰到过!你说的随机变量初始化后不再变化,本质是因为如果直接在EPL的静态表达式里调用Math.random(),它只会在查询首次编译执行时计算一次值,之后就固定了,不会每次需要的时候重新生成。下面给你几个可行的解决思路:
方法一:窗口数组+定时输出(最简洁)
Esper的窗口可以通过window()函数返回包含当前窗口内所有事件的数组,结合output every定时触发,每次输出时重新计算随机索引来选择事件:
select window()[cast(Math.random() * 2 as int)] as random_selected_event from YourEvent.win:length(2) output every 3 seconds;
- 解释:
win:length(2)始终维护最近的2个事件;output every 3 seconds确保每3秒触发一次输出;每次触发时,Math.random() * 2会重新生成0-2之间的随机数,转成int后就是0或1,对应数组里的第一个或第二个事件,完美实现随机选择。
方法二:定时器触发+嵌套查询
如果需要更灵活的控制,可以用定时器触发查询,每次触发时重新计算随机数并选择事件:
select case when Math.random() > 0.5 then latest_event else second_latest_event end as random_event from ( select (select * from YourEvent.win:length(2) order by event_time desc limit 1) as latest_event, (select * from YourEvent.win:length(2) order by event_time desc limit 1 offset 1) as second_latest_event from pattern [every timer:interval(3 sec)] );
- 解释:外层通过
pattern [every timer:interval(3 sec)]每3秒触发一次查询;每次触发时,嵌套查询会重新获取最近的两个事件,同时Math.random()会重新生成随机值,通过case语句随机选择其中一个。
关键注意点
- 确保你的事件有正确的时间字段(比如
event_time),如果用系统时间的话,Esper会自动按事件到达顺序维护窗口; - 避免把
Math.random()写在窗口的过滤条件(where子句)里,因为那里的表达式只会在查询初始化时计算一次,不会动态更新。
内容的提问来源于stack exchange,提问作者eyeweiss
相关产品推荐
相关产品推荐

