我正在开发一个小型Drools项目,因为我想了解有关使用规则引擎的更多信息。我有一个名为Event
的班级,其中包含以下字段:
String tag;
一个标签,可以是任何字符串。long millis;
时间戳。 (实际上,这是从JodaTime LocalDate
字段转换而来的,该字段也在Event
中。)int value;
我想要的价值。我在我的知识库中插入了数百个Event
个实例,现在我想获得用"OK"
标记的3个最新事件。我想出了以下代码:
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
但我觉得应该有更好的方法来做到这一点。这非常冗长,不容易重复使用:例如,如果我想用value > 10
获取最近的五个事件怎么办?我最终会复制粘贴很多代码,我不想这样做:)。
此外,代码看起来不是很漂亮&#39;对我来说。我不太喜欢重复的not Event...
限制,我也不喜欢一遍又一遍地重复相同的标记条件。 (这个例子是我真实应用程序的一个大大简化的版本,其中条件实际上要复杂得多。)
如何改进此代码?
答案 0 :(得分: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
===== edit ====
根据您的评论,以下是如何在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
请仔细检查语法,因为我正在这样做,但它应该接近这一点。