如何在 Drools 5.6 规则中定义常量集合

How to define a constant collection in Drools 5.6 rules

我正在使用 Drools 5.6。我需要将 Rules/KnowledgeBase 传送到另一个系统。我的一些规则是一种 ID 过滤器。例如,用非法语法表示,它看起来像:

rule "X":
  when
    $fact: ToBeFilteredObject(this.getId() in [1, 2, 3, 4, 5, ...])
  then
    // do something about $fact
end

"ID filter"是规则生成时确定的常量集合。由于另一个系统已经在使用 Drools KB 并且需要我提供一些其他规则,所以我将所有过滤器也作为规则提供是很自然和干净的。

但是,到目前为止,我还没有找到任何在 DRL 中声明此类常量集合的示例。请考虑以下限制条件:

  1. 因为常量是由规则生成器决定的,我不能要求客户端为这些常量插入全局事实。
  2. 过滤器可能是巨大的集合,每个可能包含 10,000 个 ID,加起来可能有 100 个 ID。使用规则将它们作为事实插入 RHS 的技巧会阻止我们使用 StatelessKnowledgeSession。但是,使用 StatefulKnowledgeSession 也是不可能的,因为我们需要在高并发环境中执行规则。我们将不得不创建许多 StatefulKnowledgeSessions 并且这些集合将在它们之间重复,使用大量内存。

理想情况下,此类文件管理器在规则定义本身中声明为常量,并保存在 KB 本身中,以便客户端可以简单地使用 StatelessKnowledgeSession

这里的 Drools 专家能否向我解释一下这是否可行?

非常感谢。

规则可以用正确的 DRL 语法写成

rule "X" // no colon here
when
  $fact: ToBeFilteredObject(id in (1, 2, 3, 4, 5) )
then
  // do something about $fact
end

请注意,可以通过其字段名称引用 属性 id,即使只有 getter 是 public。

智能生成器当然会以某种方式处理过滤器集,以减少由此产生的开销(我想),如果所有元素都会产生一个带括号的列表,那么这将是相当可观的。例如,集合 (1,2,3,4,5,6, 11,12,13,14, 21,23,25) 可以用规则

表示
rule "X"
when
  $fact: ToBeFilteredObject(id >= 1 && <= 6 || >= 11 && <= 14 || in (21,23,25) )
then
  // do something about $fact
end

最后,一点 Java 会给你一种表达任意复杂过滤器的强大方法。

class MyBitSet extends BitSet {
    MyBitSet( String bits ){
        super();
        // set bits according to the String value
    }
}

规则变为

rule "X"
when
  ToBeFilteredObject($id:id,
            new MyBitSet("01111100000111100000010101").get($id) )
then
  // do something about $fact
end

如果您确实有很多包含 "hundreds of thousands" 值的过滤器,那么根据对这些过滤器的全面分析,可能会有更好的方法。

最后,您关于有状态会话的假设是不正确的。在多个有状态会话之间共享规则库不会增加超出无状态会话所需的内存。需要记忆的是插入的事实。