流口水

时间:2011-10-13 12:25:20

标签: java rules drools

我和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,但我不确定在哪里。

希望我的问题很清楚,如果不告诉我的话。

4 个答案:

答案 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)

您可以使用modifyupdate知识助手方法更新工作记忆中的狗。如果您可以使用上述任何功能,Drools将再次重新评估规则,您最终将获得无限循环。因此,您还需要在规则中使用no-loop属性或将条件修改为

dog : Dog(age <1, isBaby == false )

以便下次再次评估相同的规则并一次又一次地将isBaby更新为true。