2013-09-24 23 views
5

Tôi đang thử thực hiện động cơ quy tắc Drools, tôi khá mới bắt đầu.drools: quy tắc được thực thi nhiều lần

tôi có các quy tắc sau tại chỗ trong một tập tin quy tắc duy nhất:

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 

Trong StatefulKnowledgeSession tôi đi qua hai tài khoản, một với sự cân bằng 15000 khác với số dư 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(); 

Theo tôi, kết quả mong đợi là mỗi quy tắc sẽ chỉ được kích hoạt một lần và đối tượng tương ứng sẽ được in.

Nhưng kết quả tôi nhận được là:

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

Tôi không thể hiểu tại sao từng quy tắc đang chạy hai lần ????

Trả lời

6

Sử dụng nhiều mẫu (và không chỉ định bất kỳ mối quan hệ nào giữa chúng) sẽ tạo ra một sản phẩm Cartes đầy đủ (giống như một lựa chọn trên nhiều bảng không có mệnh đề nối). Vì vậy, quy tắc:

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

sẽ được kích hoạt N^2 lần cho N đối tượng loại tài khoản. Một giải pháp có thể được sử dụng lĩnh vực ma thuật 'này' để xác định rằng tài khoản thứ hai cũng giống như lần đầu tiên một:

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

Nhưng, sẽ trở lại với ví dụ của bạn, tôi nghĩ rằng bạn thậm chí không cần sử dụng 2 mẫu khác nhau. Bạn có thể viết lại quy tắc của bạn như sau:

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 

Hy vọng nó giúp,

+0

Bang trên! điều này cố định nó! – Samrat

2

Tôi đã so sánh hai đối tượng cùng lớp và đã tự hỏi tại sao các quy tắc được bị sa thải nhiều lần. Tuy nhiên sau khi đọc lời giải thích từ Esteban Aliverti tôi nghĩ rằng quy tắc của tôi cũng có thể tạo ra sản phẩm Descartes.

Vì vậy, tôi đã thay thế "và" từ quy tắc thành "," và nó hoạt động hoàn hảo. Tuy nhiên, tôi không thể hiểu tại sao "và" đã tạo ra sản phẩm Descartes.

Đầu quy tắc của tôi là -

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 

Sau đó quy tắc của tôi đã trở thành (Và nó đang làm việc hoàn toàn tốt) -

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

Trong quy tắc đầu tiên, mọi mẫu sẽ được kết hợp cho mọi đối tượng RuleC trong bộ nhớ làm việc của bạn và nếu các ràng buộc khớp với quy tắc sẽ kích hoạt. Như trong "nếu có một đối tượng RuleC (đầu tiên) và có một đối tượng RuleC mà kết quả