Java Drools Core DRL - 只触发一条显着性最高的规则,跳过其他规则
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/22464163/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Drools Core DRL - Fire only one rule with the highest salience, skip other rules
提问by user3430447
I have simple JAVA bean with two int fields: 'a' and 'b'.
我有两个 int 字段的简单 JAVA bean:'a' 和 'b'。
I have two rules:
我有两个规则:
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
Actual results: "Second rule" is fired first (higher salience), "First rule" is fired second.
实际结果:首先触发“第二条规则”(更高的显着性),第二条触发“第一条规则”。
Expected results: Only one rule (with the highest salience) is fired. Other rules are ignored. How to do this? Is it possible in Drools? I am using Drools 6.0.0 Final.
预期结果:仅触发一条规则(具有最高显着性)。其他规则被忽略。这该怎么做?在 Drools 中可能吗?我正在使用 Drools 6.0.0 Final。
Requirements: 1. I can't use 'activation-group'. 2. I don't want to use 'retract' on each bean.
要求: 1. 我不能使用“激活组”。2. 我不想在每个 bean 上使用 'retract'。
UPDATE
更新
Really thanks for your answers.
真的很感谢你的回答。
Probably I should describe my problem in details. I have a set of 1500 rules. Each rule:
也许我应该详细描述我的问题。我有一套 1500 条规则。每条规则:
- works with the same bean - this bean has a lot of fields (properties),
- has salience,
- has a lot of conditions,
- has only one action - setting one (always the same) boolean flag in my bean.
- 使用同一个 bean - 这个 bean 有很多字段(属性),
- 有显着性,
- 有很多条件,
- 只有一个操作 - 在我的 bean 中设置一个(总是相同的)布尔标志。
What I want to get?When I have conflict (the input fact is matched by two or more rules) I want to fire only one rule with the highest salience. Other matched rules for this one fact should be ignored. The most important thing is performance - this should work as fast as possible.
我想得到什么?当我有冲突(输入事实与两个或更多规则匹配)时,我只想触发一个具有最高显着性的规则。应该忽略这一事实的其他匹配规则。最重要的是性能 - 这应该尽可能快地工作。
What I do?At the moment I have two solutions but I don't know which one is better or maybe I should solve this problem in different way.
我所做的?目前我有两种解决方案,但我不知道哪个更好,或者我应该以不同的方式解决这个问题。
Solution 1 - Statefull session
解决方案 1 - 有状态会话
Java code:
爪哇代码:
for (Object fact : facts) {
FactHandle fh = session.insert(fact);
session.fireAllRules(1);
session.delete(fh);
}
Solution 2 - Stateless session
解决方案 2 - 无状态会话
Java code:
爪哇代码:
for (Object fact : facts) {
session.execute(fact);
}
DRL file for solution 2: I added to each rule the same activation-group:
解决方案 2 的 DRL 文件:我向每个规则添加了相同的激活组:
rule "Rule"
activation-group "group"
salience X
when
...
then
...
回答by Esteban Aliverti
First of all let me tell you that you have some weird scenario right here :)
首先让我告诉你,你这里有一些奇怪的场景:)
There are multiple solutions for this problem:
这个问题有多种解决方案:
- Use another attribute of Bean class to mark already 'processed' facts.
- Use a custom AgendaFilter
- Use ksession.fireAllRules(1);
- 使用 Bean 类的另一个属性来标记已经“处理”的事实。
- 使用自定义 AgendaFilter
- 使用 ksession.fireAllRules(1);
Hope it helps,
希望能帮助到你,
回答by melchtheitroad55
Based on your question, I'm worried you might be misunderstanding the point of salience. Salience is a prioritization value. Drools uses it in order figure out which drool to fire first when it is the case that the constraints for more than one rule are satisfied.
根据你的问题,我担心你可能误解了显着点。显着性是一个优先级值。Drools 使用它来确定在满足多个规则的约束的情况下首先触发哪个流口水。
The problem of [firing rule P under certain circumstances and NOT rule Q when rule P is fired] is a common one. Your object model should be set up such that this is a natural consequence of reasoning over your concept space. For the literal situation you have listed, you might try inserting a new fact into working memory ("RuleFiredFact" with a value of "2nd", or whatever). You would then check for this fact in your first rule constraints. If it is true, the first rule doesn't fire.
[在某些情况下触发规则 P 并且在触发规则 P 时不规则 Q] 的问题是一个常见问题。您的对象模型应该设置为这是对您的概念空间进行推理的自然结果。对于您列出的文字情况,您可以尝试将新事实插入工作内存(“RuleFiredFact”,值为“2nd”,或其他)。然后,您将在第一个规则约束中检查这一事实。如果为真,则不会触发第一条规则。
UPDATE:To be clear, "RuleFiredFact" is an abstract placeholder for some concrete fact in your fact model. Part of the point of drools is not using abstract stuff in the drools DSL.
更新:明确地说,“RuleFiredFact”是事实模型中某些具体事实的抽象占位符。drools 的部分要点是不在 drools DSL 中使用抽象的东西。
UPDATE:
更新:
Whether or not stateful vs. stateless session is appropriate is going to depend a lot on your available computer resources, object model, team, the list goes on. If you don't know which to use, you should refer to a discussion on the topic. You might try this older mailing list post http://drools.46999.n3.nabble.com/Advice-sought-on-choosing-Stateful-or-Stateless-sessions-td57069.html
有状态与无状态会话是否合适将在很大程度上取决于您的可用计算机资源、对象模型、团队,列表还在继续。如果您不知道使用哪个,您应该参考有关该主题的讨论。你可以试试这个旧的邮件列表帖子http://drools.46999.n3.nabble.com/Advice-sought-on-choosing-Stateful-or-Stateless-sessions-td57069.html
Whichever you go with, I strongly suspect your object model is too shallow. It is very uncommon to create a drools system which contains one fact, then never creates any more. The point of drools is to reason over a number of facts. The way to tackle this is probably going to be something like moving through your object and inserting the information within it into the drools working memory as facts. You would then write rules which only fire under the constraints you want.
无论您选择哪种方式,我都强烈怀疑您的对象模型太浅了。创建一个包含一个事实的流口水系统是非常罕见的,然后再也不创建了。流口水的要点是对许多事实进行推理。解决这个问题的方法可能是在你的对象中移动并将其中的信息作为事实插入到流口水的工作记忆中。然后,您将编写仅在您想要的约束下触发的规则。
In a circumstance like what I describe, there are many ways of making sure only a single rule fires. Your rules may all be on the lookout for a "factWasAlreadyReasonedOverFact" with a reference to the fact which triggered the execution. This is a pretty rough example. Hopefully it gives you an idea.
在我所描述的情况下,有很多方法可以确保只触发一个规则。您的规则可能都在寻找“factWasAlreadyReasonedOverFact”,并引用触发执行的事实。这是一个非常粗略的例子。希望它给你一个想法。
回答by Shervin Asgari
I would solve this using activation-group
with salience
as you have described in Solution 2
我会像您在解决方案 2 中描述的那样使用activation-group
with解决这个问题salience
回答by GauRang Omar
One solution you can try is the "lock-on-active" attribute to avoid infinite execution loops involving one or more rules.
您可以尝试的一种解决方案是“lock-on-active”属性,以避免涉及一个或多个规则的无限执行循环。
Lock-on-active is scoped by a rule-group and will prevent rules from re-firing as long as the group is focused. It does not depend on new facts, or updates to the existing ones, but only on the agenda focus. If you do not manipulate groups, this may be an option.
Lock-on-active 受规则组的限制,只要该组处于焦点,就会阻止规则重新触发。它不依赖于新的事实或对现有事实的更新,而只依赖于议程重点。如果您不操作组,这可能是一个选项。
回答by Neeraj_Nitd
You can use drools.halt(); in your highest salience rule.
您可以使用drools.halt(); 在你的最高显着性规则中。
What this do is it terminate the flow and come out of rule execution (exactly what you need).
它的作用是终止流程并退出规则执行(正是您需要的)。