有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java如何在Drools规则中推断中间值

有人建议我用口水来计算分数。我不熟悉这个框架,但经过一个小的研究,我发现这确实是一个很好的解决方案,因为评分规则将被频繁更新/调整,而且编写/更改/更新Drools规则很容易

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

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

问题是:如何在单个规则之间保存(保持)这些中间值?从文档中可以看出,这是不可能的(?)或者我错过了什么。规则中没有变量

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

假设我有CANCINTRMDT1、CANCINTRMDT2、CANCINTRMDT3和一条规则calcFinalScore,它在所有以前的规则之后运行。如何传递到先前规则计算的calcFinalScore

另外,也许我的整个方法都错了,如果是的话,请纠正我


共 (1) 个答案

  1. # 1 楼答案

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

    下面是一个简单的示例,其中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
    

    这对您不起作用,因为您无法在左侧(“何时”)与这些全局对象进行交互


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

    下面是另一个简单的例子。在这里,我跟踪一个特殊对象中的一些结果,以便在后续规则中对它们进行关键点设置

    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本身中的轻量级类。它不存在于DRL之外,不能在Java中引用。因为我们只是跟踪中间值,所以没关系

    第一条规则看我们的工作记忆中是否有计算结果的实例。如果不是,则插入一个

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

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

    最后一条规则获取所有中间计算值,并(大概)对它们进行处理以计算出“最终”计算值

    我的This other answer讨论了使数据更改对其他规则可见的不同操作(insert,等等)