Drools:获取 3 个最近的事件

jqn*_*qno 5 java drools

我正在从事一个小型 Drools 项目,因为我想了解有关使用规则引擎的更多信息。我有一个名为的类Event,它具有以下字段:

  • String tag; 可以是任何字符串的标签。
  • long millis;一个时间戳。(实际上,这是从LocalDate同样在Event. 中的 JodaTime字段转换而来的。)
  • int value; 我想要推理的值。

Event在我的知识库中插入了数百个实例,现在我想获取标记为"OK". 我想出了以下代码,该代码有效:

rule "Three most recent events tagged with 'OK'"
when
    $e1 : Event( tag == "OK",
                 $millis1 : millis )
    $e2 : Event( tag == "OK",
                 millis < $millis1, $millis2 : millis )
    $e3 : Event( tag == "OK",
                 millis < $millis2, $millis3 : millis )

    not Event( tag == "OK",
               millis > $millis1 )
    not Event( tag == "OK",
               millis > $millis2 && millis < $millis1 )
    not Event( tag == "OK",
               millis > $millis3 && millis < $millis2 )
then
  # Do something with $e1.value, $e2.value and $e3.value
end
Run Code Online (Sandbox Code Playgroud)

但我觉得应该有更好的方法来做到这一点。这是非常冗长的并且不容易重用:例如,如果我想使用 获取五个最近的事件value > 10怎么办?我最终会复制粘贴很多代码,我不想这样做:)。此外,代码对我来说看起来不是很“漂亮”。我真的不喜欢重复not Event...约束,我也不喜欢一遍又一遍地重复相同的标签条件。(这个例子是我真实应用程序的一个大大简化的版本,其中的条件实际上要复杂得多。)

如何改进此代码?

Eds*_*lli 4

假设您使用 STREAM 事件处理模式并且您的事件在流中排序:

rule "3 most recent events"
when
    accumulate( $e : Event( tag == "OK" ) over window:length(3),
                $events : collectList( $e ) )
then
    // $events is a list that contains your 3 most recent 
    // events by insertion order
end
Run Code Online (Sandbox Code Playgroud)

=====编辑====

根据您的以下评论,以下是如何在 Drools 5.4+ 中实现您想要的功能:

declare window LastEvents
    Event() over window:length(3)
end

rule "OK events among the last 3 events"
when
    accumulate( $e : Event( tag == "OK" ) from window LastEvents,
                $events : collectList( $e ) )
then
    // $events is a list that contains the OK events among the last 3 
    // events by insertion order
end
Run Code Online (Sandbox Code Playgroud)

只需仔细检查语法,因为我正在背诵此操作,但它应该与此接近。