Drools:如果一组事件具有 属性 的 n 个不同值,则触发规则
Drools: Firing a rule if a set of events has n distinct values for a property
假设我们有一个具有 3 个属性的 Event
类型:constraint
、common
和 distinct
。目标是在 Drools 中编写一条规则,当满足以下条件的 Event
s 的子集存在时触发:
Event
s 发生在最后 t 秒内;和
Event
s constraint
属性 之前有一个 已知的 值;和
- 为
common
属性 分享一个先前 未知的 值;和
distinct
属性 至少有 n 个不同的值
如果规则触发,我们需要一组参与事件进行进一步处理。
你建议我们如何解决这个问题?
注1:这个问题有点类似于link,史蒂夫的回答似乎很有希望但不完整。
注2:性能至关重要。我们已经成功开发了执行此任务的规则,但它们会显着降低整个规则库的性能,因此是不可接受的。
编辑 1:当前(性能不佳的)解决方案如下所示:
rule ""
when
$event : Event(constraint == CONSTANT_VALUE)
$events : ArrayList() from collect(
Event(constraint == CONSTANT_VALUE,
common == $event.common)
over window:time( t ))
$distinctVals : Set( size >= n ) from accumulate(Event($d : distinct) from $events, collectSet($d))
then
// process $events
end
Drools 不适用于需要对潜在的大量事实进行重复评估的计算。在这种情况下,您必须将详细信息卸载到某些 Java 代码中。
class Collector {
String constraint;
String common;
List<Event> events = ...; // or Queue
Map<String,List<Event>> dist2events = ...;
int diversity;
public void addEvent( Event e ){
// 1. remove Event sets X from events older than t
// 2. remove all members of X from dist2events,
// delete map elements where the value list is empty
events.add( e );
List<Event> ofDistinct = dist2events.get( e.getDistinct() );
if( ofDistinct == null ){
ofDistinct = new ArrayList<Event>();
dist2events.put( ofDistinct );
}
ofDistinct.add( e );
diversity = dist2events.keySet().size();
}
}
rule createCollector
when
Event( $constraint: constraint, $common: common )
not Collector( constraint == constraint, common == $common )
then
insert( new Collector( $constraint, $common ) );
end
rule addEvent
when
$event: Event( $constraint: constraint, $common: common )
$collector: Collector( constraint == constraint,
common == $common,
events not contains $event )
then
modify( $collector ){ addEvent( $event ) }
end
rule MoreThan
when
Collector( $constraint: constraint, $common: common,
$events: events,
diversity >= n ) // maybe only when n-1 to n?
then
... process $events
end
您必须决定是否希望此规则仅在超过阈值 n 时触发,或者当多样性 >= n 时集合发生变化时触发。
您可能想要添加一个规则来删除空的收集器。
假设我们有一个具有 3 个属性的 Event
类型:constraint
、common
和 distinct
。目标是在 Drools 中编写一条规则,当满足以下条件的 Event
s 的子集存在时触发:
Event
s 发生在最后 t 秒内;和Event
sconstraint
属性 之前有一个 已知的 值;和- 为
common
属性 分享一个先前 未知的 值;和 distinct
属性 至少有 n 个不同的值
如果规则触发,我们需要一组参与事件进行进一步处理。
你建议我们如何解决这个问题?
注1:这个问题有点类似于link,史蒂夫的回答似乎很有希望但不完整。
注2:性能至关重要。我们已经成功开发了执行此任务的规则,但它们会显着降低整个规则库的性能,因此是不可接受的。
编辑 1:当前(性能不佳的)解决方案如下所示:
rule ""
when
$event : Event(constraint == CONSTANT_VALUE)
$events : ArrayList() from collect(
Event(constraint == CONSTANT_VALUE,
common == $event.common)
over window:time( t ))
$distinctVals : Set( size >= n ) from accumulate(Event($d : distinct) from $events, collectSet($d))
then
// process $events
end
Drools 不适用于需要对潜在的大量事实进行重复评估的计算。在这种情况下,您必须将详细信息卸载到某些 Java 代码中。
class Collector {
String constraint;
String common;
List<Event> events = ...; // or Queue
Map<String,List<Event>> dist2events = ...;
int diversity;
public void addEvent( Event e ){
// 1. remove Event sets X from events older than t
// 2. remove all members of X from dist2events,
// delete map elements where the value list is empty
events.add( e );
List<Event> ofDistinct = dist2events.get( e.getDistinct() );
if( ofDistinct == null ){
ofDistinct = new ArrayList<Event>();
dist2events.put( ofDistinct );
}
ofDistinct.add( e );
diversity = dist2events.keySet().size();
}
}
rule createCollector
when
Event( $constraint: constraint, $common: common )
not Collector( constraint == constraint, common == $common )
then
insert( new Collector( $constraint, $common ) );
end
rule addEvent
when
$event: Event( $constraint: constraint, $common: common )
$collector: Collector( constraint == constraint,
common == $common,
events not contains $event )
then
modify( $collector ){ addEvent( $event ) }
end
rule MoreThan
when
Collector( $constraint: constraint, $common: common,
$events: events,
diversity >= n ) // maybe only when n-1 to n?
then
... process $events
end
您必须决定是否希望此规则仅在超过阈值 n 时触发,或者当多样性 >= n 时集合发生变化时触发。
您可能想要添加一个规则来删除空的收集器。