簡體   English   中英

如何推斷 Drools 規則中的中間值

[英]How to infere intermediate values in Drools rules

我被推薦使用 Drools 進行分數計算。 我是這個框架的新手,但經過小型研究后,我發現它確實是一個很好的解決方案,因為評分規則將經常更新/調整,而且編寫/更改/更新 Drools 規則(看起來)很容易。

背景:我必須使用的評分算法計算中間值,然后根據這些值計算最終分數。 所以有一個名為Person的 model,它有很多屬性,其中一些可能是 null 或空的。 評分算法會考慮所有這些字段並做出最終決定(評分)。

UPD:可以跳過中間值計算(理論上),但我 100% 確定規則會變得不清楚和混亂。

問題是:如何在各個規則之間保存(持久化)這些中間值? 從文檔中可以看出,這是不可能的(?)或者我遺漏了一些東西。 規則中沒有變量這樣的東西。

理想情況下,我會有一些只能在此規則集上訪問的全局變量。 它們具有初始值(如null或 0)。

假設我有calcIntrmdt1、calcIntrmdt2、calcIntrmdt3和一個規則calcFinalScore ,它在所有先前的規則之后運行。 如何將先前規則計算的內容傳遞給calcFinalScore

PS也許我的整個方法是錯誤的,如果是這樣請糾正我

Drools確實支持“全局變量”——稱為全局變量——但您不能針對它們編寫規則。 他們通常會氣餒,但在過去,您通常 go 關於從規則集中返回值的方式。

這是一個將List作為全局的簡單示例:

global java.util.List result;

rule "All people whose name starts with 'M' will attend"
when
  $person: Person( name str[startsWith] "M" )
then
  result.add($person);
end

List<Person> attendees = new ArrayList<>();

KieSession session = this.getSession();
session.insert(person);
session.insert(person1);
session.insert(person2);
session.insert(person3);
session.insert(person4);
session.setGlobal("result", attendees);
session.fireAllRules();

// at this point, 'attendees' is populated with the result of the rules

這對您不起作用,因為您無法在左側(“when”)與這些全局變量進行交互。


相反,您需要的是一個中間值 object 來處理您的中間計算。 通常我建議將這些值存儲在對象本身上,但如果您有真正派生的數據,則沒有合適的地方將它存儲在您的模型上。

這是另一個簡單的例子。 在這里,我在臨時 object 中跟蹤一些結果,因此我可以在后續規則中關閉它們。

declare Calculations {
  intermediateValue1: int
  intermediateValue2: double
}

rule "Create tracker object"
when
  not(Calculations())
then
  insert(new Calculations())
end

rule "Calculate some intermediate value 1"
when
  $calc: Calculations()
  // some other conditions
then
  modify($calc) {
    setIntermediateValue1( 42 )
  }
end

rule "Calculate some other value using value 1 when > 20"
when
  $calc: Calculations( $value1: intermediateValue1 > 20 )
  // other conditions
then
  modify( $calc ) {
    setIntermediateValue2( $value1 * 3 )
  }
end

rule "Final calculation"
when
  $calc: Calculation( $value1: intermediateValue1 > 0,
                      $value2: intermediateValue2 > 0 )
  // other conditions
then
  // do the final calculation
end

declare關鍵字用於在 DRL 本身內有效地定義輕量級 class。 它不存在於 DRL 之外,不能在 Java 中引用。因為我們只是跟蹤中間值,所以沒關系。

第一條規則查看我們的計算結果實例是否存在於工作 memory 中。如果沒有,它會插入一個。

inserts關鍵字在這里很關鍵。 它告訴 Drools 在其工作 memory 中有新數據,它需要重新評估任何后續規則以確定它們現在是否有效以觸發。

中間兩條規則與結果 object 交互並修改值。 請注意,我不只是調用 setter(例如$calc.setIntermediateValue1( 42 ) ),而是使用modify insert類似,這讓 Drools 知道工作 memory 中的這個特定的 object 已經被修改,因此它重新評估依賴於這個 object 的任何規則,並確定它現在是否可以執行。

最后一條規則采用所有中間計算值,並且(大概)對它們做一些事情來計算出“最終”計算值。

This other answer of mine 談到了一些不同的操作( insert等),這些操作使數據更改對其他規則可見。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM