2017-10-20 157 views
0

我在使用org.drools.compiler.lang.api提供的RuleDescrBuilder API构建的DrL文件中使用以下结构。Drools:AfterMatchFiringEvent触发与OR条件相同的规则多次?

我触发了匹配后事件,以跟踪后端中每个规则的匹配数量。但是,当输入(Predicate)匹配Rule1中的所有给定条件时,它将为一个输入触发多个afterMatchFiredEvents。

import com.objects.Predicate 

global com.Util policyUtil 

dialect "java" 

rule "Rule1:RuleId" 
    salience 2147483647 
when 
    predicate := Predicate() 
    (
    eval(policyUtil.evaluate(condition1)) or 
    eval(policyUtil.evaluate(condition2)) or 
    eval(policyUtil.evaluate(condition3)) 
then 

... 

end 

rule "defaultRule:defaultRule" 
    salience 0 
when 
    predicate := Predicate() 
then 

predicate.setValue1("default1"); 
predicate.setValue2("Default2"); 
drools.halt(); 

end 

这是比赛后的事件触发:

 public void afterMatchFired(AfterMatchFiredEvent event) { 
      logger.info("Matching rule Name:: " + event.getMatch().getRule().getName()); 
      updateHitCountForRule(event.getMatch().getRule().getName()); 
     } 

这是ruledescbuilder是如何使用的。

 RuleDescrBuilder rdb = pdb.newRule(); 
     CEDescrBuilder<?, ?> cedb = rdb.lhs(); 
     cedb = cedb.and(); 
     for(each condition in rule) 
      cedb.eval().constraint(constraint).end(); 

问:为什么afterMatchFired多次触发与OR条件相同的规则?我假设eval未被正确使用。如果eval没有被正确使用,那么使用上述方法构建这种规则集的正确方法是什么?

回答

1

这是因为Drools在模式之间处理or运算符的方式。这是怎么回事幕后是Drools的创建从原来的第3个不同的规则:

rule "Rule1:RuleId 1" 
salience 2147483647 
when 
    predicate := Predicate()  
    eval(policyUtil.evaluate(condition1)) 
then 
    ... 
end 

rule "Rule1:RuleId 2" 
salience 2147483647 
when 
    predicate := Predicate()  
    eval(policyUtil.evaluate(condition2)) 
then 
    ... 
end 

rule "Rule1:RuleId 3" 
salience 2147483647 
when 
    predicate := Predicate()  
    eval(policyUtil.evaluate(condition3)) 
then 
    ... 
end 

正如你所看到的,有在Drools中的图案之间无短路or运营商。如果你所有的eval匹配,你不但会收到3次AfterMatchFiredEvent,你的规则的action部分也会被执行3次。

一个可能的方法来避免这种情况(即使它是一个有点哈克)是用事实作为标志,以免action部分执行多次:

rule "Rule1:RuleId" 
salience 2147483647 
when 
    not RuleExecuted() 
    predicate := Predicate() 
    (
     eval(policyUtil.evaluate(condition1)) or 
     eval(policyUtil.evaluate(condition2)) or 
     eval(policyUtil.evaluate(condition3)) 
    ) 
then 
    ... 
    insert(new RuleExecuted()); 
end 

在这种情况下,你会在听众中仍然收到3个BeforeMatchFiredEvent事件,但只有1 AfterMatchFiredEvent。您也将收到2个MatchCancelledEvent事件。

希望它有帮助,

+0

谢谢埃斯特万。我以eval(policyUtil.evaluate(condition1)|| policyUtil.evaluate(condition2)..)的形式在单个EVAL中执行OR条件。这只触发了一个事件并按预期工作。 – Shashank