我正在使用 Drools 5.6。我需要将规则/知识库传递到另一个系统。我的一些规则是 ID 过滤器。例如,用非法语法表示,它看起来像:
rule "X":
when
$fact: ToBeFilteredObject(this.getId() in [1, 2, 3, 4, 5, ...])
then
// do something about $fact
end
“ID 过滤器”是在规则生成时确定的常量集合。由于其他系统已经使用 Drools KB 并且需要我提供一些其他规则,因此对我来说将所有过滤器也作为规则提供是自然而干净的。
但是,到目前为止,我还没有找到任何在 DRL 中声明此类常量集合的示例。请考虑以下限制:
- 由于常量是由规则生成器确定的,因此我无法要求客户端插入此类常量的全局事实。
- 过滤器可能是巨大的集合,每个过滤器可能包含 10,000 个 ID,并且组合起来可能包含数十个 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
请注意,即使只有 getter 是公共(public)的,也可以通过属性的字段名称来引用属性 id
。
智能生成器当然会以某种方式处理过滤器集,以减少由此产生的开销,如果所有元素都会生成一个带括号的列表,那么(我认为)这将是相当大的。例如,集合 (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
如果您确实有很多包含“数十万”值的过滤器,那么基于对这些过滤器的彻底分析,可能有更好的方法。
最后,您对有状态 session 的假设是不正确的。在多个有状态 session 之间共享规则库不会增加超出无状态 session 所需的内存。插入的事实需要内存。
关于java - 如何在 Drools 5.6 规则中定义常量集合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31869760/