我有一个带有两个 int 字段的简单 JAVA bean:“a”和“b”。
我有两条规则:
rule "First rule"
salience 10
when
$bean : Bean ( a == 1)
then
$bean.setB(10);
end
rule "Second rule"
salience 20
when
$bean : Bean ( a == 1)
then
$bean.setB(20);
end
实际结果:首先触发“第二条规则”(显着性更高),然后触发“第一条规则”。
预期结果:只有一条规则(显着性最高)被触发。其他规则被忽略。这个怎么做?在 Drools 中有可能吗?我正在使用 Drools 6.0.0 Final。
要求: 1. 我不能使用“激活组”。 2. 我不想对每个 bean 都使用“retract”。
更新
非常感谢您的回答。
也许我应该详细描述我的问题。 我有一套 1500 条规则。每条规则:
- 使用同一个 bean - 这个 bean 有很多字段(属性),
- 有显着性,
- 有很多条件,
- 只有一个 Action ——在我的 bean 中设置一个(总是相同的) boolean 标志。
我想得到什么? 当我遇到冲突时(输入事实与两个或多个规则匹配)我只想触发一个显着性最高的规则。应忽略针对这一事实的其他匹配规则。最重要的是性能 - 这应该尽可能快地工作。
我做什么? 目前我有两个解决方案,但我不知道哪个更好,或者我应该以不同的方式解决这个问题。
解决方案 1 - 有状态 session
Java代码:
for (Object fact : facts) {
FactHandle fh = session.insert(fact);
session.fireAllRules(1);
session.delete(fh);
}
解决方案 2 - 无状态 session
Java代码:
for (Object fact : facts) {
session.execute(fact);
}
解决方案 2 的 DRL 文件: 我向每个规则添加了相同的激活组:
rule "Rule"
activation-group "group"
salience X
when
...
then
...
最佳答案
根据您的问题,我担心您可能误解了突出点。显着性是一个优先值。当满足多个规则的约束时,Drools 使用它来确定首先触发哪个流口水。
[在某些情况下触发规则 P 而在触发规则 P 时不触发规则 Q] 的问题很常见。你的对象模型应该被设置成这样,这是对你的概念空间进行推理的自然结果。对于您列出的字面情况,您可以尝试将一个新事实插入工作内存(“RuleFiredFact”,值为“2nd”或其他)。然后,您将在第一个规则约束中检查此事实。如果为真,则不会触发第一条规则。
更新: 明确地说,“RuleFiredFact”是事实模型中某些具体事实的抽象占位符。 drools 的部分要点是不在 drools DSL 中使用抽象的东西。
更新:
有状态 session 与无状态 session 是否合适在很大程度上取决于您可用的计算机资源、对象模型、团队等等。如果您不知道使用哪个,您应该引用有关该主题的讨论。您可以试试这个旧的邮件列表帖子 http://drools.46999.n3.nabble.com/Advice-sought-on-choosing-Stateful-or-Stateless-sessions-td57069.html
无论您选择哪种方式,我都强烈怀疑您的对象模型太浅。创建一个包含一个事实的流口水系统是非常罕见的,然后再也不会创建了。流口水的目的是对许多事实进行推理。解决这个问题的方法可能类似于移动对象并将其中的信息作为事实插入流口水工作内存中。然后,您将编写仅在您想要的约束下触发的规则。
在像我描述的情况下,有很多方法可以确保只触发一个规则。您的规则可能都在寻找“factWasAlreadyReasonedOverFact”,并引用触发执行的事实。这是一个非常粗略的例子。希望它能给你一个想法。
关于java - Drools Core DRL - 仅触发一条具有最高显着性的规则,跳过其他规则,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22464163/