如何修改Drools规则以支持personLastDatas为空时触发?
这个问题我之前也碰到过——核心原因是Drools的accumulate函数在没有匹配的源数据时,不会绑定目标变量。也就是说当$person.personLastDatas为空集合时,$maxLastDate那一行的条件根本不会匹配,规则的条件链在这里就断了,自然不会进入后续的($maxLastDate == null || ...)判断。
给你两种可行的解决方案,按需选择:
方案1:拆分条件,明确处理空集合场景
这种写法逻辑直观,把“空集合”和“有数据但日期过期”拆成两个并列分支,用or连接:
rule "Insert a too old condition modified" salience -1 when $person : Person() $tooOldInstant : DateTime() from now.minusDays(10) ( // 分支1:personLastDatas是空集合 not exists(LastData() from $person.personLastDatas) or // 分支2:存在数据,且最新的lastDate早于阈值 DateTime( this < $tooOldInstant ) from accumulate ( LastData( $date : lastDate ) from $person.personLastDatas, maxValue($date) ) ) then insert(new Condition("submitTooOldCondition")); end
方案2:自定义Accumulate逻辑,让空集合返回null
如果你更倾向于用单个Accumulate处理两种情况,可以通过init/action/result语法自定义累加逻辑,确保空集合时返回null:
rule "Insert a too old condition modified" salience -1 when $person : Person() $tooOldInstant : DateTime() from now.minusDays(10) $maxLastDate : Object() from accumulate ( LastData( $date : lastDate ) from $person.personLastDatas, init( DateTime maxDate = null; ), action( // 更新最大值:如果当前max为null,或者新日期更晚就替换 if (maxDate == null || $date.isAfter(maxDate)) { maxDate = $date; } ), result( maxDate ) // 空集合时返回null ) // 空集合时$maxLastDate为null,直接判断即可;非空时校验日期 ($maxLastDate == null || ($maxLastDate instanceof DateTime && ((DateTime)$maxLastDate).isBefore($tooOldInstant))) then insert(new Condition("submitTooOldCondition")); end
这里要注意把$maxLastDate的类型声明为Object(),因为空集合时返回的是null,Drools无法自动推断为DateTime类型。
内容的提问来源于stack exchange,提问作者Matteo Baldi
相关产品推荐
相关产品推荐

