如何在Drools中使用exists判断元素存在并引用该元素?
Drools中结合exists使用变量并避免多次匹配的解决方案
核心问题分析
Drools的exists关键字仅用于判断对象是否存在,不会将其内部子模式中绑定的变量暴露到规则的动作(then)块中,这就是你第一种写法报错$id cannot be resolved to a variable的原因。而第二种写法因为先单独匹配了所有符合条件的对象,再用exists做存在性检查,导致每个匹配对象都会触发一次规则,所以执行多次。
正确实现方式
要同时实现存在性检查(避免多次触发)和获取匹配对象的引用,需要将变量绑定放在exists包裹的完整模式内部。结合你的Rule Unit和POJO结构,正确的规则写法如下:
写法1:绑定匹配的City对象
package test; unit TestUnit; rule "test_rule" when // 检查存在至少一个TestRule,其cityList中包含name为Washington的City,并绑定该City对象 exists TestRule( $targetCity: cityList[ name == "Washington" ] ) then System.out.println("匹配到的City ID: " + $targetCity.getId()); end
写法2:直接绑定City的id属性
package test; unit TestUnit; rule "test_rule" when // 检查存在至少一个TestRule,其cityList中包含name为Washington的City,并绑定该City的id exists TestRule( cityList[ $id: id, name == "Washington" ] ) then System.out.println("匹配到的City ID: " + $id); end
为什么这个写法有效
exists关键字确保规则仅在Working Memory中存在至少一个符合条件的TestRule(其cityList包含目标City)时触发一次,避免了多次匹配的问题- 变量(
$targetCity或$id)绑定在exists包裹的TestRule模式内部,会被暴露到规则上下文,因此可以在then块中直接使用
额外说明
如果你的需求是:只要存在符合条件的City,就获取第一个匹配的对象并执行一次动作,上述写法完全满足。如果需要处理所有匹配的对象但只执行一次动作,可以结合collect关键字,但这种场景下exists的存在性检查已经足够。
内容的提问来源于stack exchange,提问作者Jasmine
相关产品推荐
相关产品推荐

