我正在尝试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
我无法理解为什么每条规则都运行两次????
答案 0 :(得分:6)
使用多个模式(并且不指定它们之间的任何关系)将创建一个完整的笛卡尔积(就像没有连接子句的多个表上的选择一样)。 所以,规则:
rule A
when
Account()
Account()
then
...
end
对于类型为Account的N个对象,将被激活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
希望它有所帮助,
答案 1 :(得分: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