【问题标题】:Esper distinct events on multiple attributesEsper 多个属性上的不同事件
【发布时间】: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 将被其他此类语句使用,因此我可以通过增加窗口的长度来解决延迟问题。 stream1stream2 按其 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


【解决方案1】:
create schema Pair(a string, b string);
create window PairWindow#length(100) as Pair;
insert into PairWindow select * from Pair;
on PairWindow as arriving select * from PairWindow as other  
  where arriving.a = other.a or arriving.b = other.b

这是一个使用命名窗口的示例自联接,该窗口保留最后 100 对。

编辑:上面的查询是为了我对原始要求的理解而设计的。下面的查询是为新的说明而设计的。它检查“a”或“b”是否有任何先前的值(在最后 100 个事件中,根据需要将 #length(100) 关闭)

create schema Pair(a string, b string);
create window PairUniqueByA#firstunique(a)#length(100) as Pair;
create window PairUniqueByB#firstunique(b)#length(100) as Pair;

insert into PairUniqueByA select * from Pair;
insert into PairUniqueByB select * from Pair;

select * from Pair as pair
  where not exists (select a from PairUniqueByA as uba where uba.a = pair.a)
  and not exists (select a from PairUniqueByB as ubb where ubb.b = pair.b);

【讨论】:

  • 感谢您的回答。我只想要一个包含某个aPair 和一个包含某个bPair。我怎样才能做到这一点?最后一条语句连接了我想从中排除一个的对,因此它产生了相反的结果。
  • 感谢您的编辑!我会看看这种方法是否按预期工作,然后回来在这里报告:)
  • 我只是查看了之前不知道的“firstunique”窗口说明符。我不能通过链接几个“firstunique”窗口说明符来完成我所寻求的吗? IE。 create window OutputPairs#firstunique(a)#firstunique(b)#length(100) as Pair ?
  • 好吧,我刚刚意识到这并不能说明uba.a = pair.bubb.b = pair.a 的可能性
  • “#firstunique(a)#length(100)”是“a”的第一个唯一事件和最后 100 个事件之间的交集。对于其他条件,您可以添加其他子查询。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-05-10
  • 2010-10-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多