当前位置: 首页 > 知识库问答 >
问题:

Drools:获取最近的3个事件

云浩然
2023-03-14

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

  • <代码>字符串标记 可以是任何字符串的标记

我在我的知识库中插入了数百个事件实例,现在我想得到3个最近的事件,它们都标记为“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

但是我有一种感觉,应该有更好的方法来做到这一点。这很冗长,不容易重复使用:如果我想获取具有值的五个最近事件怎么办

如何改进此代码


共有2个答案

狄玉书
2023-03-14

我可以这样简化“非逻辑”

rule "Three most recent events tagged with 'OK'"
when
    $e1 : Event( tag == "OK")
    $e2 : Event( tag == "OK", millis < $e1.millis )
    $e3 : Event( tag == "OK", millis < $e2.millis )
    not Event( this != $e2, tag == "OK", $e3.millis < millis, millis < $e1.millis )
then
    System.out.printf("%s - %s - %s%n", $e1, $e2, $e3);
end

没有提到清理事件。通常这是可取的,因此您可以通过删除最后一个事件来实现相同的逻辑:

rule "Three most recent events tagged with 'OK'"
when
    $e1 : Event( tag == "OK")
    $e2 : Event( tag == "OK", millis < $e1.millis )
    $e3 : Event( tag == "OK", millis < $e2.millis )
then
    System.out.printf("%s - %s - %s%n", $e1, $e2, $e3);
    retract ($e3)
end

假设每秒插入一个事件,一个“OK”,另一个为空,测试如下:

@DroolsSession("classpath:/test3.drl")
public class PlaygroundTest {
    
    @Rule
    public DroolsAssert drools = new DroolsAssert();
    
    @Test
    public void testIt() {
        for (int i = 0; i < 10; i++) {
            drools.advanceTime(1, SECONDS);
            drools.insertAndFire(new Event(i % 2 == 0 ? "OK" : "", i));
        }
    }
}

所有三种变体将产生相同的触发逻辑:

00:00:01 --> inserted: Event[tag=OK,millis=0]
00:00:01 --> fireAllRules
00:00:02 --> inserted: Event[tag=,millis=1]
00:00:02 --> fireAllRules
00:00:03 --> inserted: Event[tag=OK,millis=2]
00:00:03 --> fireAllRules
00:00:04 --> inserted: Event[tag=,millis=3]
00:00:04 --> fireAllRules
00:00:05 --> inserted: Event[tag=OK,millis=4]
00:00:05 --> fireAllRules
00:00:05 <-- 'Three most recent events tagged with 'OK'' has been activated by the tuple [Event, Event, Event]
OK4 - OK2 - OK0
00:00:06 --> inserted: Event[tag=,millis=5]
00:00:06 --> fireAllRules
00:00:07 --> inserted: Event[tag=OK,millis=6]
00:00:07 --> fireAllRules
00:00:07 <-- 'Three most recent events tagged with 'OK'' has been activated by the tuple [Event, Event, Event]
OK6 - OK4 - OK2
00:00:08 --> inserted: Event[tag=,millis=7]
00:00:08 --> fireAllRules
00:00:09 --> inserted: Event[tag=OK,millis=8]
00:00:09 --> fireAllRules
00:00:09 <-- 'Three most recent events tagged with 'OK'' has been activated by the tuple [Event, Event, Event]
OK8 - OK6 - OK4
00:00:10 --> inserted: Event[tag=,millis=9]
00:00:10 --> fireAllRules

带有窗口的变量:长度(3)也将处理最后3个OK事件。虽然开始时有所不同:1和2个first OK事件也会触发。如果会话不包含任何事件,它还会在开始时以空列表触发一次。根据文档,滑动窗口立即开始匹配,定义滑动窗口并不意味着规则必须等待滑动窗口“满”才能匹配。例如,计算窗口上事件属性的平均值的规则:长度(10)将立即开始计算平均值,对于没有事件,它将从0(零)开始,并将在事件逐一到达时更新平均值。

00:00:01 <-- 'Three most recent events tagged with 'OK'' has been activated by the tuple [InitialFactImpl, UnmodifiableRandomAccessList]
[]
00:00:01 --> inserted: Event[tag=OK,millis=0]
00:00:01 --> fireAllRules
00:00:01 <-- 'Three most recent events tagged with 'OK'' has been activated by the tuple [InitialFactImpl, UnmodifiableRandomAccessList]
[OK0]
00:00:02 --> inserted: Event[tag=,millis=1]
00:00:02 --> fireAllRules
00:00:03 --> inserted: Event[tag=OK,millis=2]
00:00:03 --> fireAllRules
00:00:03 <-- 'Three most recent events tagged with 'OK'' has been activated by the tuple [InitialFactImpl, UnmodifiableRandomAccessList]
[OK0, OK2]
00:00:04 --> inserted: Event[tag=,millis=3]
00:00:04 --> fireAllRules
00:00:05 --> inserted: Event[tag=OK,millis=4]
00:00:05 --> fireAllRules
00:00:05 <-- 'Three most recent events tagged with 'OK'' has been activated by the tuple [InitialFactImpl, UnmodifiableRandomAccessList]
[OK0, OK2, OK4]
00:00:06 --> inserted: Event[tag=,millis=5]
00:00:06 --> fireAllRules
00:00:07 --> inserted: Event[tag=OK,millis=6]
00:00:07 --> fireAllRules
00:00:07 <-- 'Three most recent events tagged with 'OK'' has been activated by the tuple [InitialFactImpl, UnmodifiableRandomAccessList]
[OK2, OK4, OK6]
00:00:08 --> inserted: Event[tag=,millis=7]
00:00:08 --> fireAllRules
00:00:09 --> inserted: Event[tag=OK,millis=8]
00:00:09 --> fireAllRules
00:00:09 <-- 'Three most recent events tagged with 'OK'' has been activated by the tuple [InitialFactImpl, UnmodifiableRandomAccessList]
[OK4, OK6, OK8]
00:00:10 --> inserted: Event[tag=,millis=9]
00:00:10 --> fireAllRules
班景龙
2023-03-14

假设您使用的是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

=====编辑====

根据您下面的评论,以下是如何在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

只要仔细检查语法,因为我正在背诵,但它应该接近这个。

 类似资料:
  • 问题内容: 我正在使用当前系统时间在表中插入数据,例如 。因此,在获取数据时,我仅需要获取最后3个小时的数据。 以下链接对我没有帮助。因为此链接使用的是我没有的特定日期格式。 从SQLite获取根据过去小时的数据 这是我的查询,但似乎无法正常工作。 插入时时间戳只不过是当前系统时间。 请给我任何参考或提示。 问题答案: 您可以使用以下方法获取3小时的时间戳记 然后,您可以传递给查询。 或者您可以在

  • 问题内容: 我在Postgres 9.3数据库中有一个方案,在该方案中,我必须获取出售书籍的最近10个日期。考虑以下示例: table中目前没有任何限制,但是我们有一项服务,每天只插入一个计数。 我必须获得基于的结果。当我传递ID时,应使用书名,出售日期和出售份数生成报告。 所需的输出: 问题答案: 这看起来并不令人怀疑,但这 是个难题 。 假设条件 你的数目是。 表格中的所有列均已定义。 该表在

  • 这是正确的工作,但它绘制了许多标记的坐标小于600米的用户的位置。我想要的是只在折线的最近点画一个标记。某种程度上评估来自用户的<600的所有coord,然后选择最接近的。感谢任何帮助。

  • 问题内容: 我有一个历史记录表,该表存储了用户对延缓帖子执行的所有操作 我想要的是让最后三个用户完成所有操作 问题答案: 假设是一列, SQLFiddle演示

  • 目前正在尝试ScalaFX。 设想如下: 我有一些节点,它们由一些边连接。 我更喜欢的是类似于 如何在JavaFX中检测特定点的节点? 或 JavaFX 2.2在坐标处获取节点(可视化树点击测试) 这些问题基于JavaFX的旧版本,并使用了不推荐的方法。 到目前为止,我还没有在ScalaFX8中找到任何替代或解决方案。有没有一个很好的方法来获得一定半径内的所有节点?

  • 问题内容: 我需要在活动中获得并显示照片库中最近拍摄的3张照片,而无需任何点击。 完成此步骤后,滚动时,我应该以3 x 3的方式拍摄其他照片。 您知道快速执行此操作的正确方法吗?谢谢。 问题答案: 这是使用适用于iOS 8+设备的框架的解决方案: