流口水在一段时间内没有达到规则
Posted
技术标签:
【中文标题】流口水在一段时间内没有达到规则【英文标题】:Drools Absence of hitting a rule over a perios of time 【发布时间】:2020-12-09 10:15:05 【问题描述】:我是 Drools 的新手。我需要使用 spring-boot & Drools(7.40.0.Final) 构建一个应用程序,其中 springboot 应用程序流式传输一个外部源,该源将持续触发数据包(跟踪与实体移动相关的数据)到我的应用程序。我需要评估所有这些流数据。
我正在使用“geofence_rule.drl”文件来保存与地理位置相关的规则。
rule "Rule for Tag position in room 1"
when
model : ComponentModel(positionValue <= 50)
then
model.setRoomId(1);
end
rule "Rule for Tag position in room 2"
when
model : ComponentModel(positionValue > 50)))
then
model.setRoomId(2);
end
模型类如下。
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class ComponentModel
private long tagId;
private long roomId;
private int positionValue;
我可能会得到“n”个标签的位置相关数据,比如tag1、tag2、tag3等等。我需要计算过去 5 分钟内,Room-1 中是否不存在 tag1(这意味着 tag-1 的数据未达到“房间 1 中的标签位置规则”)。 Drools 是否支持这种计算?
我在drools 文档中看到了“not”关键字。但它只是否定了规则的条件。我需要检查最后几分钟的规则命中性质,这个时间限制可以在应用程序中配置。
【问题讨论】:
【参考方案1】:您正在寻找stream mode 和negative patterns。这些链接指向 Drools 官方文档。
流模式是 Drools 中的两种事件模式之一。默认为“云”模式,您可以在其中预先了解所有事实并自动做出决策。另一种模式“流”模式用于处理时间流,这听起来很像您的“ping”应用程序。在流模式下,Drools 会在每个事实进入时对其进行评估,并知道时间——即其他事实何时进入。
流模式中的否定模式是not
关键字的逻辑时间扩展。正如您正确指出的那样,在云模式下,它只是否定一个条件(例如,“工作记忆中没有与此条件匹配的条件。”)但是,在流模式下,您可以更新这些模式以在一段时间内生效时间。
Drools 文档提供了这个例子:
rule "Sound the alarm"
when
$h: Heartbeat() from entry-point "MonitoringStream"
not(Heartbeat(this != $h, this after[0s,10s] $h) from entry-point "MonitoringStream")
then
// Sound the alarm.
end
“when”子句中的第一行标识了一个心跳实例 ($h
)。第二个标识在 10 秒内未收到心跳的情况。如果两个条件都为真,则执行规则——在这种情况下会触发警报。
这与您应用于规则的模式相同。
rule "Tag has not been in Room 1 for 5 minutes"
when
// Tag with ID 1, present in Room 1 -- First instance
$tag: ComponentModel( tagId == 1, roomId == 1 ) from entry-point "TrackingStream"
// Trigger if this condition hasn't been met a second time within 5 minutes
not( ComponentModel(
this != $tag,
tagId == 1,
roomId == 1,
this after[0s, 5m] $tag ) from entry-point "TrackingStream")
then
// Do whatever it is you need to do for this condition
end
在这种情况下,我使用了 after
时间运算符(链接到 Drools 文档。)
基本上就是这样工作的--
$tag: ComponentModel( tagId == 1, roomId == 1 ) from entry-point "TrackingStream"
第一个条件标识场景,在这种情况下,房间 1 中存在 ID 1。它标识了我们正在跟踪的那个场景的当前实例。由于这是一个时间流,因此很容易将其视为“标记实体 (1) 刚刚进入房间 1。”
not( ComponentModel(
this != $tag,
tagId == 1,
roomId == 1,
this after[0s, 5m] $tag
) from entry-point "TrackingStream")
这就是魔法发生的地方,语法需要一点时间来适应。第二个条件是等待 next 时间然后检查条件。检查的条件是:
TagID 为 1, RoomId 为 5时间约束 (this after[0s, 5m] $tag
) 表示等待检查此条件。如果在$tag
之后的此时间范围内收到第二个 ComponentModel,则规则不会触发,并且场景将重复等待最多 5 分钟。由于时间范围[0s, 5m]
立即开始检查,我们需要在not(...)
子句的匹配中明确排除$tag
(this != $tag
。)
为了说明,这就是它的执行方式(简化):
0m:00s - 事件 A ~ 已收到(id = 1,房间 = 1)。$tag
= 事件 A。我们开始检查传入流的第二个条件。
0m:30s - 事件 B ~ 收到(id = 2,房间 = 1)。身份不匹配;忽略。
0m:45s - 事件 C ~ 收到(id = 1,房间 = 1)。事件规则匹配“已取消”。现在检查 $tag
= 事件 C。
5m:45s - 在 5 分钟窗口内未收到匹配事件,事件 C 的规则触发右侧。
【讨论】:
感谢@Roddy 的回复。 负面模式现在很清楚了。我还想再包括一项检查,即否定规则的相反条件。在流模式下,就像“缺席”检查一样,需要检查如下,规则“标签在房间 1 中持续存在 5 分钟”当 <...conditions...> 然后roomId != 1
,因为这表明标签 1 在不同的房间中。
根据您的第一条评论,在“0m:45s - Event C ~ 收到(id = 1,room = 1)。EventA 规则匹配“已取消”并检查 $tag = EventC”。但是当我自己尝试时,EventA 并没有被取消。最终结果显示 EventA 和 eventC 被触发。以上是关于流口水在一段时间内没有达到规则的主要内容,如果未能解决你的问题,请参考以下文章