如何推断 Drools 规则中的中间值

How to infere intermediate values in Drools rules

有人推荐我使用 Drools 计算分数。我是这个框架的新手,但经过一些小的研究,我发现它确实是一个很好的解决方案,因为评分规则将经常 updated/adjusted 并且很容易(看起来)write/change/update Drools 规则.

背景:我必须使用的评分算法计算中间值,然后根据这些值计算最终分数。 所以有一个名为 Person 的模型,它有很多属性,其中一些可能为 null 或为空。评分算法会考虑所有这些字段并做出最终决定(评分)。

UPD: 可以跳过中间值计算(理论上),但我 100% 确定规则会变得不清楚和混乱。

问题是:如何保存(持久化)这些中间值 个人规则之间?从文档中可以看出,这是不可能的(?)或者我遗漏了一些东西。规则中没有可变的东西。

理想情况下,我会有一些只能在此规则集上访问的全局变量。它们具有初始值(如 null 或 0)。

假设我有 calcIntrmdt1、calcIntrmdt2、calcIntrmdt3 和一个规则 calcFinalScore,它是 运行 在所有先前规则之后。如何将先前规则计算的内容传递给 calcFinalScore

P.S。也许我的整个方法是错误的,如果是这样请纠正我

Drools 支持“全局变量”——称为全局变量——但您不能针对它们编写规则。他们通常会气馁,但在过去,这通常是您从规则集中返回值的方式。

这是一个简单的示例,其中 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”)与这些全局变量交互。


相反,您需要的是一个中间对象来处理您的中间计算。通常我会建议将这些值存储在对象本身上,但如果你有真正派生的数据,那么没有合适的地方将它存储在你的模型上。

这是另一个简单的例子。在这里,我在一个临时对象中跟踪一些结果,因此我可以在后续规则中关闭它们。

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 中引用。由于我们只是跟踪中间值,所以没关系。

第一条规则查看我们的计算结果实例是否存在于工作内存中。如果不是,则插入一个。

inserts 关键字在这里很关键。它告诉 Drools 它的工作内存中有新数据,它需要重新评估任何后续规则以确定它们现在是否有效。

中间两条规则与结果对象交互并修改值。请注意,我不只是调用 setter(例如 $calc.setIntermediateValue1( 42 )),而是使用 modify。类似于 insert,这让 Drools 知道工作内存中的这个特定对象已被修改,因此它会重新评估依赖此对象的任何规则并确定它现在是否可以执行。

最后一条规则采用所有中间计算值,并(大概)对它们进行一些处理以计算出 'final' 计算值。

我的

谈到了使数据更改对其他规则可见的不同操作(insert 等)。