【发布时间】:2019-02-02 21:11:52
【问题描述】:
我对 Esper 中的流语义有疑问。我的目标是只输出具有成对不同属性的事件。此外,属性之间还存在一些时间条件(参见 Espers Interval Algebra Reference)。
示例语句:
insert into output_stream select a.*, b.*
from stream1#length(100) as a, stream2#length(100) as b
where a.before(b) or a.meets(b) or a.overlaps(b)
成对不同的属性意味着,我想确保没有两个输出 o1, o2 where o1.a = o2.a or o1.b = o2.b。举个更具体的例子,如果有结果
o1: (a = a1, b = b1),
o2: (a = a1, b = b2),
o3: (a = a2, b = b2),
o4: (a = a2, b = b1)
只应输出其中两个(例如 o1 和 o3 或 o2 和 o4)。哪个暂时不重要。
我想用这样的NOT EXISTS 子句来完成成对的不同属性:
NOT EXISTS (
select * from output_stream#length(100) as otherOutput
where a = otherOutput.a or b = otherOutput.b )
这部分有效,对于连续输出,断言o1.a = o2.a or o1.b = o2.b 始终成立。
但是,当stream1 首先提供多个“a”,然后stream2 提供一个“b”,这与要与两个“a”连接的条件相匹配时,一次会有多个输出 。这不在我的NOT EXISTS 子句中,因为在同一步骤中会出现多个具有相同“b”的输出,因此它们还没有在output_stream 中。
distinct 关键字在这里不合适,因为它会同时检查所有属性,而不是成对检查。同样,所有属性上的简单group by 也不合适。我希望有类似“a 上不同,b 上不同”之类的标准,但它不存在。
我可以使用嵌套的group bys 来解决这个问题,我在每个属性上进行分组
select first(*) from (select first(*) from output_stream group by a) group by b
但根据一条评论,在流处理系统中没有明确定义的语义。因此,Esper 不允许在查询的 from 部分中使用子查询。
我需要的是一种强制一次只输出一个输出的方法,因此在每个进一步的输出上重新检查NOT EXISTS 条件,或者在实际插入之前以某种方式检查同时发生的输出将它们放入流中。
更新:
输出的时序不是很关键。 output_stream 将被其他此类语句使用,因此我可以通过增加窗口的长度来解决延迟问题。 stream1 和 stream2 按其 startTimestamp 属性的顺序传递事件。
【问题讨论】:
-
不要抛出一些 EPL 设计,而是从需求开始,并提供一些示例事件和预期输出。从这个讨论中,我无法真正猜测成对不同属性的含义。这就像有人发布一些 Java 代码并期望人们猜测需求。
-
From 子句在像 Esper 这样的流处理器中具有无限的结果。关系数据库中的 From 子句具有有限的结果(只是查询时表中已经存在的行)。因此 from 子句中的子查询在流处理中没有定义的语义。因此,在流式处理中,您必须始终指定结果应该出现的时间。 IE。结果应该每分钟出现一次吗?还是针对每个传入事件?或者对于某个流的每个传入事件?还是别的什么?
-
谢谢,我会调整问题以提供一些示例。只是为了快速响应,我认为两个结果元组 (a1, b1), (a1, b2) 的属性不是成对不同的。 (a1, b1), (a2, b2) 或 (a2, b1), (a1, b2) 但是是成对不同的。
-
a 和 b 之间的组合不能是随机的,但要遵循特定的条件。例如,可能存在
a.overlaps(b)(见esper.espertech.com/release-8.0.0/reference-esper/html/…)的条件。 -
见这篇文章stackoverflow.com/questions/46917625/…。您也许可以将这对封装到一个对象中并为其实现“hashCode”和“equals”并将其视为单个值。
标签: group-by stream distinct esper