英文:
is it possible to write rules on instances rather than classes in drools?
问题
我试图使用Drools编写类似以下内容的规则,但不确定如何操作。
我有以下内容:
MyData d = new MyData();
MyData d1 = new MyData();
d.setValue(10);
d1.setValue(10);
这是我想要实现的规则:
rule "data d value equals 10"
when
d.getValue() == 10;
then
doSmthg();
end
如果我将LHS更改为
$d: MyData(Value == 10)
那么doSmthg()将被执行两次。
那么,是否有办法仅针对MyData类的一个实例编写规则,而不是所有MyData类的实例?
PS:我需要将d和d1都插入kieSession,因为我有其他涉及所有实例的规则。
英文:
I am trying to write something like this with drools but I am not sure how to go about it.
I have the following :
MyData d = new MyData();
MyData d1 = new MyData();
d.setValue(10);
d1.setValue(10);
and this is the rule I would like to implement :
rule "data d value equals 10 "
when
d.getValue()==10;
then
doSmthg();
end
if I were to change the LHS to
$d: MyData(Value ==10)
the doSmthg() would be executed twice.
So is there a way to write the rule only about one instance instead of all the instances of the MyData class??
PS: I need to insert both d and d1 in the kieSession because I have other rules that involve all the instances.
答案1
得分: 1
你需要针对规则中的特定实例进行操作。或者如果两个项目相同,你只希望在给定条件下触发规则一次,你可以插入一个标志或其他构造来阻止它多次触发。
例如,假设你有两个值都为10的MyData。你希望触发规则的一个还具有一个布尔标志latest = true。
因此,你的工作内存中有:
MyData( value = 10, latest = true ) // 我们希望触发此规则
MyData( value = 10, latest = false ) // 不希望触发此规则
然后我们会修改我们的规则以检查latest标志。
rule "Data value is 10, latest"
when
$d: MyData( value == 10, latest == true )
then
$d.doSmthg();
end
或者,如果这两个对象实际上是相同的,没有任何唯一之处,而我们只想基于MyData的值为10的存在触发规则,你有两种方法可以实现。
第一种方法是使用exists
- 只要在工作内存中存在符合此条件的实例,它就会触发。只要你不通过调用update
重新评估规则,这应该满足你的需求。但请注意,在这种情况下,你无法引用对象。
rule "Any data value with 10 exists"
when
exists( MyData(value == 10) )
then
doSmthg(); // 必须是函数或静态导入;不能是实例方法
end
如果你需要针对实例执行操作,就不能使用exists
,而必须插入一个标志或以其他方式阻止规则再次触发。最简单的方法是将某些内容插入到工作内存中,以充当标志。
rule "Data value is 10, with flag"
when
not( String(this == "DATA_10") ) // 如果内存中不存在标志
$d: MyData( value == 10 )
then
$d.doSmthg();
insert( "DATA_10" ); // 插入标志
end
总结一下,你的选择是:
- 如果可能的话,以唯一特征作为关键。
- 如果不需要实例引用,可以使用
exists
。 - 插入标志或其他流程控制机制,以防止规则第二次触发。
英文:
You need to target the specific instance in your rule. Or if both items are the same and you just want the rule to fire once for a given condition, you can insert a flag or other construct to keep it from firing multiple times.
For example, let's say that you have two MyData with value = 10. The one you do want to fire the rule also has a boolean flag latest = true.
So your working memory has:
MyData( value = 10, latest = true ) // we want to trigger the rule with this
MyData( value = 10, latest = false ) // and not this
Then we'd modify our rule to also check for the latest flag.
rule "Data value is 10, latest"
when
$d: MyData( value == 10, latest == true )
then
$d.doSmthg();
end
Alternatively if both objects are actually the same and there's nothing unique about them, and we just want to trigger based on the presence of a MyData with value 10, you have two ways to do this.
The first way is to use exists
-- this just fires if there exists an instance in working memory that meets this criteria. As long as you never re-evaluate the rule by calling update
, this should suit your needs. Note however that you have no reference to the object in this case.
rule "Any data value with 10 exists"
when
exists( MyData(value == 10) )
then
doSmthg(); // must be function or static import; cannot be instance method
end
If you do need to do work against the instance, you can't use exists and instead have to insert a flag or otherwise keep the rule from firing again. Easiest way is to insert something into working memory to act as a flag.
rule "Data value is 10, with flag"
when
not( String(this == "DATA_10") ) // if flag does not exist in memory
$d: MyData( value == 10 )
then
$d.doSmthg();
insert( "DATA_10" ); // insert flag
end
So to summarize, your options are:
- Key off of a unique characteristic if possible
- Use
exists
if you don't need an instance reference - Insert a flag or other flow control mechanism to keep the rule from firing a second time.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论