流口水在一段时间内没有达到规则

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 modenegative 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(...) 子句的匹配中明确排除$tagthis != $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...> 然后 end 我们如何实现这种规矩? 简单,只需在规则中更改roomId签入即可。如果标签从未出现在该窗口的任何其他房间中,则标签会在房间 1 中存在五分钟。因此,只需检查条件中的roomId != 1,因为这表明标签 1 在不同的房间中。 根据您的第一条评论,在“0m:45s - Event C ~ 收到(id = 1,room = 1)。EventA 规则匹配“已取消”并检查 $tag = EventC”。但是当我自己尝试时,EventA 并没有被取消。最终结果显示 EventA 和 eventC 被触发。

以上是关于流口水在一段时间内没有达到规则的主要内容,如果未能解决你的问题,请参考以下文章

jbpm 进程未使用 ruleFlowGroup 触发流口水规则

流口水规则流

使用junit进行流口水测试

如何在流口水规则引擎中处理列表项中对象的先前值?

关联规则之序列模式挖掘--GSP算法

流口水 vs JBPM ?差异,优点和缺点