我们使用drools规则引擎5x我们有一个规则配置如下
事实{A,B,C},行动X事实{A,B},行动Z
当我通过{A,B,C}时,我得到了两个动作X,Z。这是drools引擎预期的行为吗?可以将C定义为可选事实吗?在这种情况下,这是可能的吗?
发布于 2022-11-30 15:27:21
工作正常。这两条规则都符合开火的条件,所以这两条规则都是开火的。
如果您不希望在传递C条件时触发AB规则,则需要编写它,这样它就不会显式地触发。
下面是一个例子:
rule "ABC"
when
A()
B()
C()
then
System.out.println("ABC");
end
rule "AB not C"
when
A()
B()
not( C() )
then
System.out.println("AB not C");
end在本例中,如果将对象A、B和C传递到规则中,则只会触发第一个规则,因为第二个规则是相互排斥的:只有在不存在C时才会触发。类似地,如果您只传递A和B,而不传递C,那么只有第二个规则会触发,因为第一个规则需要C,并且没有满足要求。
如果没有not( C() )条件,那么您在示例中就有了:规则将触发,而不管C对象在内存中的存在(或脓肿),因为它是完全无关的。你会问你是否可以让C是可选的--正如你所拥有的,C是可选的。它是否存在并不重要。
请注意,您如何否定条件"C“取决于它实际上是什么。如果您的事实是这样的:MyObj( a == 1, b == 2, c >= 3),那么您将通过在:MyObj( a == 1, b == 2, c < 3)上设置AB规则键来否定C。您只需反转"C“条件检查,不管它是什么。
为了完整起见,值得一提的是,您可以修改工作内存中的项,以防止第二条规则在第一条规则发生后触发。如果这两条规则生活在真空中,这可能会成为你的解决方案;如果它们是一个更大的规则集的一部分,可能会有其他规则依赖于这些相同的事实,这可能会导致意想不到的后果。
首先,您可以在工作内存中插入一个“标志”,并在您不想触发的规则中关闭它的存在(或不存在)。因此,如果不希望AB触发,如果ABC被触发,则可以在ABC规则的右侧插入一个标志:
declare Flag
name: String
end
rule "ABC with flag"
when
A()
B()
C()
then
Flag f = new Flag();
f.setName("ABC");
insert( f )
end
rule "AB but not if ABC"
when
A()
B()
not( Flag(name = "ABC" ))
then
//...
end在这里,规则ABC在发射时插入一个标志;规则AB在发射之前检查是否存在该标志。
或者,您可以从工作内存中提取retract事实,以便不再触发要求该数据的规则。这可能会产生深远的后果(数据实际上是从工作内存中删除的,因此当Drools重新评估所有有效规则时,可能会触发意外的规则),因此通常不建议您这样做。
https://stackoverflow.com/questions/74555512
复制相似问题