6

我正在尝试使用 Drools 规则引擎,我是个初学者。

我在单个规则文件中有以下规则:

rule "A stand alone rule" 
salience 2
no-loop
when
    $account : Account()
    Account($account.balance>100)
then
    System.out.println("balance>100");
    System.out.println($account.getBalance());
    System.out.println($account.getCustomer().getName());    
end

rule "A second Rule"
salience 1
no-loop
when
    $account : Account()
    Account($account.balance<100)
then
    System.out.println("balance<100");
    System.out.println($account.getBalance());
    System.out.println($account.getCustomer().getName());
end 

在 StatefulKnowledgeSession 中,我传递了两个帐户,一个余额为 15000,另一个余额为 15,

Account account=new Account(7l,15000l);
        Account account1=new Account(5l,15l);

        Customer customer = new Customer("Samrat", 28, "Sector51", account);
        Customer customer1 = new Customer("Alexi", 28, "Sector50", account1);
        account.setCustomer(customer);
        account1.setCustomer(customer1);
        session.insert(account);
        session.insert(account1);

        session.fireAllRules();

根据我的预期结果应该是每个规则应该只触发一次并且应该打印相应的对象。

但我得到的结果是:

balance>100
15000
Samrat
balance>100
15000
Samrat
balance<100
15
Alexi
balance<100
15
Alexi

我无法理解为什么每条规则运行两次????

4

2 回答 2

7

使用多个模式(并且不指定它们之间的任何关系)将创建一个完整的笛卡尔积(就像在没有连接子句的多个表上进行选择一样)。所以,规则:

rule A
when
    Account()
    Account()
then
    ...
end

将为 N 个 Account 类型的对象激活 N^2 次。一种解决方案是使用魔术字段“this”来指定第二个帐户与第一个帐户相同:

rule A
when
    $a: Account()
    Account(this == $a)
then
    ...
end

但是,回到你的例子,我认为你甚至不需要使用 2 种不同的模式。你可以重写你的规则如下:

rule "A stand alone rule" 
salience 2
no-loop
when
    $account: Account(balance>100)
then
    System.out.println("balance>100");
    System.out.println($account.getBalance());
    System.out.println($account.getCustomer().getName());    
end

rule "A second Rule"
salience 1
no-loop
when
    $account: Account(balance<100)
then
    System.out.println("balance<100");
    System.out.println($account.getBalance());
    System.out.println($account.getCustomer().getName());
end

希望能帮助到你,

于 2013-09-24T13:41:05.613 回答
2

我正在比较同一类的两个对象,并且想知道为什么规则会被多次触发。然而,在阅读了 Esteban Aliverti 的解释后,我认为我的规则也可能是创建笛卡尔积。

因此,我将规则中的“和”替换为“,”,并且效果很好。但是,我不明白为什么“和”会创建笛卡尔积。

早些时候我的规则是——

rule "Rule 1"
    when
       $first : RuleC() and
       second : RuleC(this != $first) and
           RuleC($first.outcome < outcome) and 
           RuleC($first.target == target)
    then
        System.out.println("The rule has been fired ");
end

后来我的规则变成了(它工作得很好)——

rule "Rule 1"
    when
       $first : RuleC() and
       second : RuleC(this != $first, $first.outcome < outcome, $first.target == target)
    then
        System.out.println("The rule has been fired ");
end
于 2014-01-18T09:59:38.053 回答