Is there anyway to filter rules before matching?

860 views
Skip to first unread message

Infeligo

unread,
Dec 22, 2014, 3:50:03 PM12/22/14
to drools...@googlegroups.com
I would like to filter rules based on meta information. I want to be able to do that before any activation (matching) is done in order to gain performance. AgendaFilter and enabled attribute do their work after matching. Packages do not suit me because I have too many different combinations that depend on runtime data. Is there any way to do this?

Davide Sottara

unread,
Dec 22, 2014, 4:15:01 PM12/22/14
to drools...@googlegroups.com
First of all, which version are you using? 5.x creates matches eagerly, as facts are inserted. 6.x is lazy and will wait until you try to fire the rules, possibly reducing the need for the kind of optimization you are considering.

This said, you might consider the declarative agenda, aka "meta-rules". For example, see the unit tests here:
https://github.com/droolsjbpm/drools/blob/master/drools-compiler/src/test/java/org/drools/compiler/integrationtests/DeclarativeAgendaTest.java

The idea is that every activation creates a "Match" object that can be predicated upon using a rule. Matches expose metadata in the form of @attributes on the regular rules,
and can block, fire, reschedule or cancel the actual firing.

Providing more details about your use case might also help :)

On Mon, Dec 22, 2014 at 9:50 PM, Infeligo <mih...@gmail.com> wrote:
I would like to filter rules based on meta information. I want to be able to do that before any activation (matching) is done in order to gain performance. AgendaFilter and enabled attribute do their work after matching. Packages do not suit me because I have too many different combinations that depend on runtime data. Is there any way to do this?

--
You received this message because you are subscribed to the Google Groups "Drools Usage" group.
To unsubscribe from this group and stop receiving emails from it, send an email to drools-usage...@googlegroups.com.
To post to this group, send email to drools...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/drools-usage/0e46a0ce-bf46-4860-8cf6-9c3a2847a129%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Infeligo

unread,
Dec 23, 2014, 10:50:23 AM12/23/14
to drools...@googlegroups.com
Thanks for your answer, Davide. Here is what I am trying to achieve from business side:

I have a bunch of documents that contain fields. I use Drools to calculate one fields from other fields in these documents. The problem is that document contains a period flag (year/month combination) and depending on that calculations can be different. For example, in 2015-05 one rule is used to calculate some stuff, but since for 2015-08 and older docs another, slightly changed rule has to be used. As you see, I have identical left-part of the rules ("when"), so in time, when the number of rule versions increases, it might become a performance problem.

Davide Sottara

unread,
Jan 3, 2015, 8:23:44 AM1/3/15
to drools...@googlegroups.com
If your rules have (almost) identical LHSs, node sharing should help reduce the impact on performance.
So, this indeed becomes a conflict resolution problem in presence of multiple versions of the "same" rule.
This is a very common problem with rules derived from norms/laws.

Unfortunately there is no way to filter rules before matching (there are many ways to filter rules before FIRING, though), especially
if your filter criteria depend on a flag/field that is part of your fact. The simplest solution I can think of is to use meta-rules, as
previously suggested. Have your temporally constrained facts implement some interface that exposes the temporal flag and
annotate your rules, something along these lines:

rule "Calculate some stuff"
@Temporal( from="2015-05-01", until="2015-08-01" )
when
  $d : Document()
 ...
then .... end

rule "Check"
@Direct
when
  $m : Match( $f : from, $u : until, $facts : objects )
  Timed( flag < $f || > $u )  from $objects
  // assuming Document implements this interface. Also use date, timestamp or temporal operators as needed
  // also having the Timed fact always in the same position, e.g. as the first fact, allows to replace "from" with an array index
then
 $m.cancel();
end

Assume a given document matches N temporal rules, and only one needs to ultimately fire.
You get 2*N - 1 matches - the N rules and N - 1 matches of the meta-rule.
You also get N firings : N-1 firings of the meta-rule will cancel the undesired activations, letting
the only one that is appropriate fire and generate the results.
You pay a price in term of matches, but you won't need to process the conflicting calculations.


The alternative is to embed the temporal constraints directly to the rules

rule "Calculate some stuff"
when
  $d : Document( flag > "2015-05-01" && < "2015-08-01" )
  ...
then .... end

This is more efficient: eventually you will get only 1 match and 1 firing, but requires to mix the business
logic with the control logic, which in some cases is unacceptable.

Based on your use case, let me know if you need a more detailed discussion on either solution
Best
Davide






Davide Sottara

unread,
Jan 3, 2015, 8:58:31 AM1/3/15
to drools...@googlegroups.com
Another possibility is to use the attributes "date-effective" and "date-expires".
The attributes, however, consider the session clock rather than the facts.

However, if you can insert facts preserving the temporal order given by the
flag/timestamp and if you can sync the (pseudo-)clock appropriately, this
may be the most efficient option since it prevents rules from activating in
the first place.

Davide
Reply all
Reply to author
Forward
0 new messages