在 drools 中使用 EXISTS 关键字满足条件时从 WHEN 部分获取值
Getting value from WHEN part while a condition meets using EXISTS keyword in drools
rule "attaching AV and impact rating"
agenda-group "evaluate likelihood"
dialect "java"
when
Application($threatList:getThreatList())
$av:AttackVector()
exists $threat:Application.Threats(impact == "Disclose Information")from $threatList
exists AttackVector($av == AttackVector.REQUEST_MANIPULATION)
then
RiskRating riskRating=new RiskRating($threat.getImpactRating(),$av.getLikelihood(),$av.getName());
insertLogical(riskRating);
end
我正在努力在上述规则的 THEN 部分获取对象 $threat
。如果我运行上面的规则,它说:
Rule Compilation error : [Rule name='attaching AV and impact rating']
referee/security/attack/Rule_attaching_AV_and_impact_rating1426933818.java (7:1053) : $threat cannot be resolved
如果我遍历它并在 THEN 部分获取值,它会生成笛卡尔积并在会话中多次插入这些值。当我得到笛卡尔积时,我的规则看起来像这样。
rule "attaching AV and impact rating"
agenda-group "evaluate likelihood"
dialect "java"
when
Application($threatList:getThreatList())
$av:AttackVector()
exists $threat:Application.Threats(impact == "Disclose Information")from $threatList
$threat:Application.Threats(impact == "Disclose Information")from $threatList
exists AttackVector($av == AttackVector.REQUEST_MANIPULATION)
then
RiskRating riskRating=new RiskRating($threat.getImpactRating(),$av.getLikelihood(),$av.getName());
insertLogical(riskRating);
end
如何在没有笛卡尔积的情况下获取 THEN 部分中 $threat
的值?
完全删除 exists
操作。
rule "attaching AV and impact rating"
agenda-group "evaluate likelihood"
dialect "java"
when
Application($threatList:getThreatList())
$av: AttackVector()
$threat: Application.Threats(impact == "Disclose Information")from $threatList
exists(AttackVector($av == AttackVector.REQUEST_MANIPULATION))
then
RiskRating riskRating=new RiskRating($threat.getImpactRating(),$av.getLikelihood(),$av.getName());
insertLogical(riskRating);
end
exists
的意思是“工作记忆中有一个东西像这样匹配这些conditions/looks”。它不用于实际提取或提供对该匹配实例的引用。只需删除运算符,它就会按照您的需要工作——如果有一个 Application.Threats
符合您的条件,规则就会触发并将匹配值分配给 $threat
变量。
你 运行 的事实是你有 多重 威胁,这意味着你的情况,这就是为什么你有多个规则触发器-- 每次匹配 Application.Threats
触发一次。 exists
关键字缓解了这一点,因为它只关心至少存在一个匹配项,但您没有得到引用(因为如果有四个匹配项,哪一个将分配给变量?这没有意义,逻辑上。)
因此您需要更改规则,使其不会触发多次,而只会在找到匹配项时触发一次。通常你会通过让后果对工作记忆做一些事情来做到这一点,从而使规则不再有资格被解雇。在您的示例中,您插入了一个 RiskRating 对象;然后,您可以检查您的条件中是否不存在风险评级:
not( RiskRating( /* insert criteria here or leave empty */ ) )
或者,您可以从工作记忆中撤回您的规则存在或匹配所依赖的内容。例如,如果你以后不需要它,你可以收回攻击向量:
retract( $av )
另一种选择可能是尝试将您的 getThreatList()
实施更新为 return Set,这样您就不会重复(假设威胁被认为是重复的,基于 'impact' 字段。)或者您可以尝试从正在 returned 的威胁列表中删除所有符合条件的 Application.Threats 实例。
我们对您的用例或规则集知之甚少,无法知道您需要什么数据或它看起来像什么,但归根结底,您只需要规则触发一次且仅触发一次,所以要做到这一点,您需要以某种方式更新规则以了解它不再有效。
rule "attaching AV and impact rating"
agenda-group "evaluate likelihood"
dialect "java"
when
Application($threatList:getThreatList())
$av:AttackVector()
exists $threat:Application.Threats(impact == "Disclose Information")from $threatList
exists AttackVector($av == AttackVector.REQUEST_MANIPULATION)
then
RiskRating riskRating=new RiskRating($threat.getImpactRating(),$av.getLikelihood(),$av.getName());
insertLogical(riskRating);
end
我正在努力在上述规则的 THEN 部分获取对象 $threat
。如果我运行上面的规则,它说:
Rule Compilation error : [Rule name='attaching AV and impact rating']
referee/security/attack/Rule_attaching_AV_and_impact_rating1426933818.java (7:1053) : $threat cannot be resolved
如果我遍历它并在 THEN 部分获取值,它会生成笛卡尔积并在会话中多次插入这些值。当我得到笛卡尔积时,我的规则看起来像这样。
rule "attaching AV and impact rating"
agenda-group "evaluate likelihood"
dialect "java"
when
Application($threatList:getThreatList())
$av:AttackVector()
exists $threat:Application.Threats(impact == "Disclose Information")from $threatList
$threat:Application.Threats(impact == "Disclose Information")from $threatList
exists AttackVector($av == AttackVector.REQUEST_MANIPULATION)
then
RiskRating riskRating=new RiskRating($threat.getImpactRating(),$av.getLikelihood(),$av.getName());
insertLogical(riskRating);
end
如何在没有笛卡尔积的情况下获取 THEN 部分中 $threat
的值?
完全删除 exists
操作。
rule "attaching AV and impact rating"
agenda-group "evaluate likelihood"
dialect "java"
when
Application($threatList:getThreatList())
$av: AttackVector()
$threat: Application.Threats(impact == "Disclose Information")from $threatList
exists(AttackVector($av == AttackVector.REQUEST_MANIPULATION))
then
RiskRating riskRating=new RiskRating($threat.getImpactRating(),$av.getLikelihood(),$av.getName());
insertLogical(riskRating);
end
exists
的意思是“工作记忆中有一个东西像这样匹配这些conditions/looks”。它不用于实际提取或提供对该匹配实例的引用。只需删除运算符,它就会按照您的需要工作——如果有一个 Application.Threats
符合您的条件,规则就会触发并将匹配值分配给 $threat
变量。
你 运行 的事实是你有 多重 威胁,这意味着你的情况,这就是为什么你有多个规则触发器-- 每次匹配 Application.Threats
触发一次。 exists
关键字缓解了这一点,因为它只关心至少存在一个匹配项,但您没有得到引用(因为如果有四个匹配项,哪一个将分配给变量?这没有意义,逻辑上。)
因此您需要更改规则,使其不会触发多次,而只会在找到匹配项时触发一次。通常你会通过让后果对工作记忆做一些事情来做到这一点,从而使规则不再有资格被解雇。在您的示例中,您插入了一个 RiskRating 对象;然后,您可以检查您的条件中是否不存在风险评级:
not( RiskRating( /* insert criteria here or leave empty */ ) )
或者,您可以从工作记忆中撤回您的规则存在或匹配所依赖的内容。例如,如果你以后不需要它,你可以收回攻击向量:
retract( $av )
另一种选择可能是尝试将您的 getThreatList()
实施更新为 return Set,这样您就不会重复(假设威胁被认为是重复的,基于 'impact' 字段。)或者您可以尝试从正在 returned 的威胁列表中删除所有符合条件的 Application.Threats 实例。
我们对您的用例或规则集知之甚少,无法知道您需要什么数据或它看起来像什么,但归根结底,您只需要规则触发一次且仅触发一次,所以要做到这一点,您需要以某种方式更新规则以了解它不再有效。