【问题标题】: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”关键字。但它只是否定了规则的条件。我需要检查最后几分钟的规则命中性质,这个时间限制可以在应用程序中配置。

【问题讨论】:

    标签: java spring-boot streaming drools rules


    【解决方案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 被触发。
    猜你喜欢
    • 2011-12-06
    • 1970-01-01
    • 1970-01-01
    • 2018-02-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-12
    相关资源
    最近更新 更多