用好Drools 中的表达式是你的规则引擎能否强大的必要条件
下面列出了几个个人认为比较重要的点:
AND
Drools 默认的并列表达式就是 前置的AND
(and Cheese( cheeseType : type ) Person( favouriteCheese == cheeseType ) ) when Cheese( cheeseType : type ) Person( favouriteCheese == cheeseType ) then ...
OR
OR 实际上并不是按照||的短路逻辑进行处理的, 而是将一个规则写为两个子规则, 分别匹配和执行
(or Person( sex == "f", age > 60 ) Person( sex == "m", age > 65 ) pensioner : ( Person( sex == "f", age > 60 ) or Person( sex == "m", age > 65 ) ) (or pensioner : Person( sex == "f", age > 60 ) pensioner : Person( sex == "m", age > 65 ) )
NOT
there must be none of...
相当于work memory必须没有所示表达式的对象, 建议写()
// Brackets are optional: not Bus(color == "red") // Brackets are optional: not ( Bus(color == "red", number == 42) ) // "not" with nested infix and - two patterns, // brackets are requires: not ( Bus(color == "red") and Bus(color == "blue") )
EXIST
there is at least one..
相当于work memory至少有一个所示的对象
exists Bus(color == "red") // brackets are optional: exists ( Bus(color == "red", number == 42) ) // "exists" with nested infix and, // brackets are required: exists ( Bus(color == "red") and Bus(color == "blue") )
FORALL
WorkMemory中所有facts都需要符合表达式, 可以支持多项匹配
单项匹配
rule "All Buses are Red"
when
forall( Bus( color == 'red' ) )
then
// all Bus facts are red
end
多项顺序匹配, 所有英文的bus都是红色的
rule "All English buses are red" when forall( $bus : Bus( type == 'english') Bus( this == $bus, color = 'red' ) ) then // all English buses are red end
更复杂的情况, 所有employee都有health和dental care
rule "all employees have health and dental care programs" when forall( $emp : Employee() HealthCare( employee == $emp ) DentalCare( employee == $emp ) ) then // all employees have health and dental care end
FROM
从fact中拿出匹配表达式的field, 支持 基本类型 和 集合类, 如果是集合类且有多个符合条件的field, rule会fire多次
rule "apply 10% discount to all items over US$ 100,00 in an order" when $order : Order() $item : OrderItem( value > 100 ) from $order.items then // apply discount to $item end
只要value>100就会被fire一次, 相当于 遍历items, 判断并执行 for item in items: if value > 100 then ....
rule "Assign people in North Carolina (NC) to sales region 1" ruleflow-group "test" lock-on-active true when $p : Person( ) $a : Address( state == "NC") from $p.address then modify ($p) {} // Assign person to sales region 1 in a modify block end rule "Apply a discount to people in the city of Raleigh" ruleflow-group "test" lock-on-active true when $p : Person( ) $a : Address( city == "Raleigh") from $p.address then modify ($p) {} // Apply discount to person in a modify block end
如果person在Raleign, NC生活, 应该两个rule都被Fire, 实际上, 只有第二个rule被fire, 原因是lock-on-active 当一系列fact变化时, 阻止rule进行新的activition, 所以第一个rule没有被再次active, 如果没有fact发生变化, 则一切正常
注意点:
-
Avoid the use of
from
when you can assert all facts into working memory or use nested object references in your constraint expressions (shown below). -
Place the variable assigned used in the modify block as the last sentence in your condition (LHS).
-
Avoid the use of
lock-on-active
when you can explicitly manage how rules within the same rule-flow group place activations on one another (explained below).
Accumulate
将WorkMemory中的每个fact中的值进行累加操作, 内嵌支持min max avg count sum collectList collectSet, 也可以自己实现org.drools.core.runtime.rule.TypedAccumulateFunction
接口, 从而写出自己的accumulate 函数
rule "Raise alarm" when $s : Sensor() accumulate( Reading( sensor == $s, $temp : temperature ); $min : min( $temp ), $max : max( $temp ), $avg : average( $temp ); $min < 20, $avg > 70 ) then // raise the alarm end
其他注意点:
ruleflow-group
default value: N/A
type: String
Ruleflow is a Drools feature that lets you exercise control over the firing of rules. Rules that are assembled by the same ruleflow-group identifier fire only when their group is active.
规则流是一个Drools的功能,让你在规则的fire进行控制。即用相同的规则流组只有当他们的group active时才会被fire。
agenda-group
default value: MAIN
type: String
Agenda groups allow the user to partition the Agenda providing more execution control. Only rules in the agenda group that has acquired the focus are allowed to fire.
Agenda 允许用户进行分区并提供更多的执行控制。只有在 agenda group 被focus的时候才可以被fire
auto-focus
default value: false
type: Boolean
When a rule is activated where the auto-focus value is true and the rule's agenda group does not have focus yet, then it is given focus, allowing the rule to potentially fire.
可以让没有被focus的 agenda group获得 focus, 允许rule去执行
activation-group
default value: N/A
type: String
Rules that belong to the same activation-group, identified by this attribute's string value, will only fire exclusively. More precisely, the first rule in an activation-group to fire will cancel all pending activations of all rules in the group, i.e., stop them from firing.
Note: This used to be called Xor group, but technically it's not quite an Xor. You may still hear people mention Xor group; just swap that term in your mind with activation-group.
属于activation-group的rules将进行 独占式的触发, 更准确地说,一个已被fire的规则可以阻止所有的未执行规则
date-effective
default value: N/A
type: String, containing a date and time definition
A rule can only activate if the current date and time is after date-effective attribute.
一个rule只能在当前时间或者当前时间之后被触发
date-expires
default value: N/A
type: String, containing a date and time definition
A rule cannot activate if the current date and time is after the date-expires attribute.
一个rule不能在当前时间或者当前时间之后被触发
duration
default value: no default value
type: long
The duration dictates that the rule will fire after a specified duration, if it is still true.
rule将在duration时间之后被fire