【问题标题】:Esper counting repeating events in pattern埃斯珀以模式计数重复事件
【发布时间】:2023-03-22 20:41:01
【问题描述】:

我有一系列事件是这样的:

  1. 事件 A 开始序列
  2. 多个事件 B 发生
  3. 事件 C 停止序列

我使用模式 [每个 A -> (B 直到 C)] 做到了这一点,这似乎是正确的(你怎么看?)。但我正在努力从序列中出现的 B 事件中检索和汇总信息。我想简单地计算一下,也许还有一些平均值,但似乎没有任何效果(示例 1 返回 1,示例 2 返回 0,示例 3 返回 null,即使我的 B 事件存在)。

insert into CreateMeasurement
select
    C.source            as source,
    "carDrivingAnalyse" as type,
    C.time              as time,
    {
        "example1", count(*),
        "example2", count(B),
        "example3", B.countOf()
    } as fragments

from pattern [
    every A = EventCreated(
        type = "Ignition",
        getString(A, "Ignition.status") = "ON")

    -> (
        B = EventCreated(
            type = "DrivingEvent",
            source = A.source,
            getString(B, "DrivingEvent.prop1") = getString(A, "Ignition.prop1"),
            getNumber(B, "DrivingEvent.prop2") = getNumber(A, "Ignition.prop2"))

        until C = EventCreated(
            type = "Ignition",
            getString(C, "Ignition.status") = "OFF",
            source = A.source,
            getString(C, "Ignition.prop1") = getString(A, "Ignition.prop1"),
            getNumber(C, "Ignition.prop2") = getNumber(A, "Ignition.prop2"))
    )
]

【问题讨论】:

    标签: aggregate esper cumulocity


    【解决方案1】:

    我会为这个用例选择不同的方法并使用上下文而不是模式:

    create context EventContext
      context PartionBySource
        partition by event.source.value from EventCreated,
      context ContextBorders
        initiated by EventCreated(type="EventA") as startEvent 
        terminated by EventCreated(event.type="EventC");
    

    它已经是一个更复杂的上下文,因为它使用了两个嵌套的上下文。这是 Cumulocity 文档 (http://cumulocity.com/guides/event-language/advanced/#contexts) 中对上下文的一些基本介绍,但对于这种高级用法,我建议使用更详细的 esper 文档 http://www.espertech.com/esper/release-5.3.0/esper-reference/html/context.html

    总的来说,这个上下文是这样做的:

    基于 EventCreated 流,它将首先按源设备对事件进行分区。每次有 EventA 时,它都会创建一个新的上下文分区(仅当此时此设备没有上下文分区时)。随着 EventC 的到来,该设备的上下文分区将结束。

    现在你可以像这样使用这个上下文:

    context EventContext
    select
      count(*) as count,
      avg(getNumber(e, "speed")) as speed
    from EventCreated e
    where e.event.type = "EventB"
    output last when terminated;
    

    此语句使用上下文。它将在上下文分区结束的那一刻输出结果(所以当 EventC 到达时)。它只会输出最后一个事件(此处没有 last 关键字,它将输出分区处于活动状态时收到的每个事件)。 在本例中,它将输出上下文分区存在期间接收到的事件数以及EventB中“速度”片段的平均值。

    请注意,这里没有必要按源进行任何过滤,因为上下文已经对 EventCreated 上的事件进行了分区。

    【讨论】:

    • 感谢您的回答,我正在阅读 esper 文档,并且正在尝试编写上下文,但我已经在努力翻译我的模式。看,我通过说事件 B 和 C 必须具有与 A 相同的源来简化我的示例,但实际上它们有更多属性要检查(我编辑了我的原始帖子),现在我无法复制 getString/getNumber在我的上下文中起作用。
    • 另外,条件计数呢?类似 "e.countOf(event -> getNumber(event, "c8y_HarshBehavior.speed") > 100)" 除了这不起作用。
    • 我会将 getNumber(event, "c8y_HarshBehavior.speed") > 100 放到 where 子句中
    • 我不能那样做,我有很多事情要计算......就像我想要平均速度,还有速度大于 100 的事件数,它的次数介于 50 到 10 之间,等等。
    • 刚刚在 esper 解决方案模式中找到了一些示例。您可以像这样使用计数count(*, getNumber(event, "c8y_HarshBehavior.speed") > 100)。刚刚试了一下,效果很好。仅当布尔表达式为真时才计数。
    【解决方案2】:

    我不是专家,但“count()”从不返回“null”。在这方面,您的观察可能是错误的。 “count()”是一个聚合函数,用于计算 from 子句中任何内容的出现次数。对于模式,它会计算模式匹配的数量。

    “count(B)”计算表达式中(不同的)非空值的数量,请参阅 doc。这也不会返回“null”。

    “example3”是您想要的,只是根据您的测试数据确保实际上有多个 B 事件在 C 事件之前到达。

    【讨论】:

    • 我错了,你是对的,示例 1 (count(*)) 在逻辑上返回 1,因为整个模式匹配一​​次。示例 2 (count(B)) 返回 0,示例 3 (B.countOf()) 返回 null,就像没有创建事件 B 一样。然而事实并非如此,有事件 B。
    • 简化语句并在此处发布使用 EPL 工具的示例。 EPL 工具链接为esper-epl-tryout.appspot.com/epltryout/mainform.html
    猜你喜欢
    • 1970-01-01
    • 2010-09-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-10
    相关资源
    最近更新 更多