2013-09-24 14 views
5

Sto provando con le mani sul motore di regole Drools, sono un principiante.drools: regole eseguite più volte

ho le seguenti norme in vigore in un unico file regola:

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 

Nel StatefulKnowledgeSession sto passando due conti, uno con equilibrio 15000 un'altra con equilibrio 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(); 

Secondo me il risultato atteso dovrebbe essere che ogni regola dovrebbe essere sparata una sola volta e l'oggetto corrispondente dovrebbe essere stampato.

Ma il risultato che sto ottenendo è:

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

io non sono in grado di capire il motivo per cui ogni regola è in esecuzione due volte ????

risposta

6

L'utilizzo di più motivi (e non la specifica di alcuna relazione tra loro) creerà un prodotto cartesiano completo (proprio come una selezione su più tabelle senza una clausola join). Quindi, la regola:

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

sarà attivato N^2 volte per N oggetti di tipo di account. Una soluzione potrebbe essere quella di utilizzare il campo magia 'questo' per specificare che il secondo account è lo stesso di prima:

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

Ma, tornando al tuo esempio, penso che non si nemmeno bisogno usare 2 modelli diversi. Si potrebbe riscrivere le regole come segue:

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 

Speranza che aiuta,

+0

Bang on! questo l'ha risolto! – Samrat

2

mi stava confrontando due oggetti della stessa classe e si chiedeva il motivo per cui le regole sono sempre sparato più volte. Tuttavia, dopo aver letto la spiegazione di Esteban Aliverti, ho pensato che la mia regola potesse anche essere la creazione di un prodotto cartesiano.

Quindi ho sostituito "e" dalle regole a "," e ha funzionato perfettamente. Tuttavia, non riuscivo a capire perché "e" stavo creando un prodotto cartesiano.

All'inizio la mia regola era -

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 

Più tardi la mia regola è diventato (e si sta lavorando assolutamente bene) -

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 
+0

Nella prima regola ogni modello verrà abbinato per ogni oggetto RuleC nella memoria di lavoro e se i vincoli corrispondono alla regola sparerà. Come in "se c'è un oggetto RuleC (prima) e c'è un oggetto RuleC per quale esito