我和drools有一个奇怪的问题:
我有以下规则:
rule "is my dog a baby?"
ruleflow-group "dog"
salience 10
when
dog : Dog(age <1 )
then
dog.setIsBaby(true);
end
rule "baby dog"
ruleflow-group "dog"
salience 9
when
myData : MyData( myDog.isBaby() == false)
then
System.out.println(myData.getMyDog().getIsBaby());
end
我在会话中插入myData和myData.getMyDog()
,其中myData.getMyDog.isBaby==false
第一条规则被解雇了,我的狗将成为一个婴儿。然后第二个被触发,甚至它打印为真。(即使条件是假的)
当我在解雇所有规则后进行测试时,myData中的myDog将成为一个婴儿。
我在这里做错了什么?为什么要解雇第二条规则?是会话中的问题(在我的情况下是有状态的)?
我认为我需要说我修改了myData:myDog,但我不确定在哪里。
希望我的问题很清楚,如果不告诉我的话。
答案 0 :(得分:15)
修改工作记忆事实时,您需要告诉Drools数据已更改,以便重新评估所有相关规则。
Drools在触发任何匹配的规则之前评估事实。如果你有一只年龄= 0且baby = false的狗,你的规则都将被激活。当您的is my dog a baby?
规则被触发时,它不会改变当Drools评估baby dog
规则时,myDog.isBaby() == false
条件为真的事实。
要告知Drools您已修改了某些事实,请使用update()
知识帮助程序方法。请记住,Drools将事实句柄与特定对象相关联。如果规则引用MyData
,并且您希望在MyData.myDog
对象发生更改时重新评估该规则,则需要在update()
对象上使用MyData
;只在update()
对象上执行Dog
,不会导致baby dog
规则重新评估。
尝试将is my dog a baby?
规则更改为以下内容:
rule "is my dog a baby?"
ruleflow-group "dog"
salience 10
when
dog : Dog(age < 1, baby == false)
myData : MyData(myDog == dog)
then
dog.setIsBaby(true);
update(dog);
update(myData);
end
答案 1 :(得分:9)
你需要做
then
dog.setIsBaby(true);
update( dog )
在您的第一条规则上,并重写第二条规则的 ,如
when
dog : Dog( isBaby == false)
myData : MyData( myDog == dog)
规则必须以这种方式编写,因此drools可以自动检测事实发生变化后必须再次运行的规则。
每次更改规则引擎中的事实时,您都需要通过更新告诉工作内存您已更改它。
我从版本4开始没有使用过drools,但我认为这仍然适用。
答案 2 :(得分:2)
是的,你应该更新狗和地图。 干杯
答案 3 :(得分:0)
您可以使用modify
或update
知识助手方法更新工作记忆中的狗。如果您可以使用上述任何功能,Drools将再次重新评估规则,您最终将获得无限循环。因此,您还需要在规则中使用no-loop属性或将条件修改为
dog : Dog(age <1, isBaby == false )
以便下次再次评估相同的规则并一次又一次地将isBaby更新为true。