在 lhs 和 rhs 中流口水变量的不同值
Drools different value of variable in lhs and rhs
我有两条规则
rule "test1"
when
$cr: MyContext(flag1 == 1)
then
System.out.println("<---- Test1 start ---->");
$cr.setFlag1(10);
System.out.println("<---- Test1 end ---->");
end
rule "test2" salience -1
when
$cr: MyContext($flag1: flag1 == 1)
then
System.out.println("<---- Test2 start ---->");
System.out.println($flag1);
System.out.println("<---- Test2 end ---->");
end
I rule1,我正在检查变量 MyContext.flag1 是否为 1。因为它是 true,所以我将其更改为 10。
我规则 2,我正在检查变量 MyContext.flag1 是否为 1。
没想到这条规则会执行,因为 flag1 是 10.
但令人惊讶的是,它执行并将 flag1 打印为 10。
如何在规则 2 的左轴将 flag1 == 1 评估为真,而在右轴打印 flag1 将其评估为 10?
最初,Drools 根据您工作记忆中的事实评估必须触发两条规则。所以要解雇的规则的议程是(根据你的显着性):
- 等待被解雇的规则“test1”...
- 等待被解雇的规则“test2”...
你想念的是,如果你不这么说 Drools,议程就不会被修改。
在你的情况下,规则“test1”被触发,然后从议程中删除,议程的新状态是:
- 等待被解雇的规则“test2”...
那么接下来会发生什么,规则“test2”被触发,并且由于您更改了事实,drools 打印了它的新值,即 10。所以行为正常。
您需要在规则“test1”中修改后调用 update($cr),这意味着:根据我的事实 $cr 使用所有规则更新议程。
结果是 Drools 现在将从其议程中删除规则“test2”。
当您启动 drools 规则时,框架会在工作内存中获取您的规则输入并确定哪些规则匹配。然后对这些规则匹配进行排序(按显着性或自然顺序),然后按顺序触发。
因此,当您触发规则时,“test1”和“test2”被确定为匹配项。然后 Drools 继续首先触发“test1”,然后是“test2”。
如果您希望 Drools 重新评估规则匹配,您需要“告诉”框架您对工作记忆进行了更改。为此,您有以下内置方法:
Method
Explanation
insert
Put a new fact into working memory.
delete
or retract
Removes some information (object/s) from working memory.
update
Update/replace a fact in working memory.
modify
Change fields inside of a fact in working memory.
这些方法还有一些“合乎逻辑”的版本,您可以在 Drools documentation.
中阅读更多内容
如果您在进行更改时或更改后不使用这些内置框架方法,您将继续评估初始的规则匹配集。这些更改实际上对 Drools 是不可见的,因为您还没有告诉 Drools “嘿,我们已经进行了更改。”每个规则的左侧已根据原始数据集进行了评估;右侧根据匹配顺序进行评估。
所以在你的情况下,你想要做的是使用 modify
函数告诉 Drools 你正在对工作记忆中的一条信息应用更改。
rule "test1"
when
$cr: MyContext(flag1 == 1)
then
modify( $cr ) {
setFlag1(10)
}
end
需要注意的一件事是如何评估规则匹配。当您调用 insert
将新数据放入工作内存时,Drools 将对规则匹配进行 partial 重新评估。已经匹配执行的规则不会再运行;仅重新评估后续规则以确定它们现在是否匹配。
相比之下,update
将对所有规则进行全面评估。它的功能等同于停止当前规则的执行并使用工作内存中的新数据调用 fireAllRules
。
如果您的规则具有外部副作用或不是幂等的,调用 update
可能会产生严重的副作用,因为您可能会在数据更改时多次评估规则的 RHS。
我有两条规则
rule "test1"
when
$cr: MyContext(flag1 == 1)
then
System.out.println("<---- Test1 start ---->");
$cr.setFlag1(10);
System.out.println("<---- Test1 end ---->");
end
rule "test2" salience -1
when
$cr: MyContext($flag1: flag1 == 1)
then
System.out.println("<---- Test2 start ---->");
System.out.println($flag1);
System.out.println("<---- Test2 end ---->");
end
I rule1,我正在检查变量 MyContext.flag1 是否为 1。因为它是 true,所以我将其更改为 10。 我规则 2,我正在检查变量 MyContext.flag1 是否为 1。 没想到这条规则会执行,因为 flag1 是 10.
但令人惊讶的是,它执行并将 flag1 打印为 10。
如何在规则 2 的左轴将 flag1 == 1 评估为真,而在右轴打印 flag1 将其评估为 10?
最初,Drools 根据您工作记忆中的事实评估必须触发两条规则。所以要解雇的规则的议程是(根据你的显着性):
- 等待被解雇的规则“test1”...
- 等待被解雇的规则“test2”...
你想念的是,如果你不这么说 Drools,议程就不会被修改。 在你的情况下,规则“test1”被触发,然后从议程中删除,议程的新状态是:
- 等待被解雇的规则“test2”...
那么接下来会发生什么,规则“test2”被触发,并且由于您更改了事实,drools 打印了它的新值,即 10。所以行为正常。
您需要在规则“test1”中修改后调用 update($cr),这意味着:根据我的事实 $cr 使用所有规则更新议程。 结果是 Drools 现在将从其议程中删除规则“test2”。
当您启动 drools 规则时,框架会在工作内存中获取您的规则输入并确定哪些规则匹配。然后对这些规则匹配进行排序(按显着性或自然顺序),然后按顺序触发。
因此,当您触发规则时,“test1”和“test2”被确定为匹配项。然后 Drools 继续首先触发“test1”,然后是“test2”。
如果您希望 Drools 重新评估规则匹配,您需要“告诉”框架您对工作记忆进行了更改。为此,您有以下内置方法:
Method | Explanation |
---|---|
insert |
Put a new fact into working memory. |
delete or retract |
Removes some information (object/s) from working memory. |
update |
Update/replace a fact in working memory. |
modify |
Change fields inside of a fact in working memory. |
这些方法还有一些“合乎逻辑”的版本,您可以在 Drools documentation.
中阅读更多内容如果您在进行更改时或更改后不使用这些内置框架方法,您将继续评估初始的规则匹配集。这些更改实际上对 Drools 是不可见的,因为您还没有告诉 Drools “嘿,我们已经进行了更改。”每个规则的左侧已根据原始数据集进行了评估;右侧根据匹配顺序进行评估。
所以在你的情况下,你想要做的是使用 modify
函数告诉 Drools 你正在对工作记忆中的一条信息应用更改。
rule "test1"
when
$cr: MyContext(flag1 == 1)
then
modify( $cr ) {
setFlag1(10)
}
end
需要注意的一件事是如何评估规则匹配。当您调用 insert
将新数据放入工作内存时,Drools 将对规则匹配进行 partial 重新评估。已经匹配执行的规则不会再运行;仅重新评估后续规则以确定它们现在是否匹配。
相比之下,update
将对所有规则进行全面评估。它的功能等同于停止当前规则的执行并使用工作内存中的新数据调用 fireAllRules
。
如果您的规则具有外部副作用或不是幂等的,调用 update
可能会产生严重的副作用,因为您可能会在数据更改时多次评估规则的 RHS。