2017-10-20 155 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