Groupby – a new way to accumulate facts in DRL

A drawing demonstrating using groupby to get the lowest priced fruit of each kind when all fruit come from the same source.

Have you ever wanted to accumulate facts that share a particular property (for instance, the count of people in each department) in DRL? With the addition of groupby to DRL, it is easier to write rules that divide facts into groups where each group is accumulated separately. In this post, we’ll explain what groupby is, how to use it, and give examples of groupby usage.

What is groupby?

Groupby is a new syntax construct introduced in 8.41.0.Final for dividing facts into groups, allowing each group to be accumulated separately. It has the following syntax:

groupby(source-pattern; grouping-key; accumulators [; constraints])

Where:

  • source-pattern: Pattern used to gather facts that will be grouped and accumulated. For instance, using $a: /applicants[age < 21] as the source-pattern would group and accumulate all Applicants under the age of 21 (binding the applicant to $a, which can be used in the grouping-key and accumulators).
Info
The examples in this article use the OOPath syntax for source-pattern, but the traditional syntax is also supported. For more details, see the Rule Language Reference.
  • grouping-key: A function used to divide the source-pattern into separate groups. Facts from source-pattern for which grouping-key returns the same value are grouped together. The key can optionally be bound to a variable, allowing it to be used outside the groupby. For example, using $country: $a.country as the grouping key would group applicants by country, binding the country for the group to the $country variable.
  • accumulators: One or more accumulate functions used to accumulate the facts in each group. Each accumulate function can optionally be bound to a variable, allowing it to be used outside the groupby. For instance, $count: count() would count the number of applicants younger than 21 from each country.
  • constraints: Optional constraints on the group key and accumulation result. The rest of the rule will only execute for the given group key if all constraints return true. For instance, $count >= 100 would only continue execution of the rule for a given $country if that country have at least 100 applicants younger than 21.

Combining the above example together, we get:

groupby(
    $a: /applicants[age < 21];
    $country: $a.country;
    $count: count();
    $count >= 100
)

How to use groupby

You can use groupby by upgrading Drools to 8.41.0.Final or later. Groupby can then be used in your DRL files like any other language construct (such as forall and accumulate).

Example groupby usage

Groupby is a good choice whenever you need to accumulate results for separate groups. Some examples of rules that can be implemented with it include:

  • Get departments over budget
rule "Departments over budget"
    groupby($order: /order;
            $department: $order.department;
            $totalCost: sum($order.cost);
            $totalCost > $department.budget
    )
then
    // ...
end
  • Find days which are understaffed
rule "Understaffed Days"
    groupby($shift: /shifts[ employee != null ];
            $date: $shift.date;
            $assignedCount: count();
            $assignedCount < $date.minimumAssignedShifts
    )
then
    // ...
end
  • Get the highest bid for a product
rule "Highest bid for a product"
    groupby($bid: /bids;
            $product: $bid.product;
            $highestBid: max($bid)
    )
then
    // ...
end

Conclusion

Groupby is a new language feature introduced in 8.41.0.Final that allows for simpler grouping of objects by a key function. You can use it by upgrading Drools to 8.41.0.Final or later. Groupby is useful for implementing rules that accumulate facts that share a given property, such as getting the total cost by department or getting the highest bidder by product.

5 1 vote
Article Rating
Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments