我正在尝试建立一条流口水的规则,其中所提供的事实具有用户提供的int值。事实也有一个具有预期的int值的对象的列表。我需要检查用户提供的值是否小于单个对象期望值的总和。这是我的示例事实类-
public class Order {
private int orderId;
private List<OrderItem> orderItems;
private int usersIntegrationFee;
}
事实类中包含的OrderItem类是-
public class OrderItem {
private int orderItemId;
private Product prod;
}
并且Product类是具有productIntegrationFee字段的一类-
public class Product {
private String mktProdId;
private String prodName;
private int productIntegrationFee;
}
我希望检查Order.usersIntegrationFee是否小于所有Order.OrderItem.Product.productIntegrationFee的总和。有没有办法在流口水中做到这一点?任何帮助将不胜感激。
您需要使用一个名为accumulate
的drools内置实用程序。该实用程序允许您在“累加”某种变量值的同时,在右侧迭代对象的集合。一些常见的用例涉及总和,均值,计数等。基本上,构造方法会遍历集合中的每个项目,并对每个项目执行一些已定义的操作。
虽然您可以定义自己的自定义累加函数,但Drools支持几个内置的累加函数-其中之一是sum
。此内置功能是您特定用例所需的。
accumulate
的一般格式是这样的:accumulate( <source pattern>; <functions> [;<constraints>] )
。您的规则应如下所示(伪代码,因为我在这台计算机上没有Drools;语法应接近或精确,但可能存在错别字。)
rule "Integration fee is less than sum of product fees"
when
// extract the variables from the Order
Order( $userFee: usersIntegrationFee,
$items: orderItems)
// use the accumulate function to sum up the product fees
$productFees: Integer( this > $userFee ) from
accumulate( OrderItem( $product: prod ) from $items,
Product( $fee: productIntegrationFee ) from $product;
sum($fee) )
then
// do something
end
一些注意事项。在单个accumulate
中,您可以执行多项操作-求和,求平均值,等等。但是,如果您仅像这样调用一个累加函数,则可以使用我已经显示的语法[Integer( conditions ) from accumulate( ... )
。)如果您有多个函数,则必须直接分配输出(例如$sum: sum($fee)
,等)
最后,accumulate
还有第三个可选参数,由于您的用例非常简单并且不需要它,因此我省略了它。第三个参数应用过滤(称为“约束”),以便累加函数跳过不符合此条件的项目。例如,您可以添加一个约束以忽略负数的productIntegrationFee值,如下所示:$fee > 0
。
关于我在此规则中选择的语法的最后说明。由于用例是“如果usersIntegrationFee小于总和,则触发规则”,因此将比较直接放在Integer( ... ) from accumulate
中。当然,您可以单独进行比较,例如Integer( $productFees > this ) from $userFee
或您喜欢的任何其他格式的比较。这种方式似乎最简单。
Drools documentation具有有关此实用程序的更多信息。我已经链接到讨论“何时”子句中的元素的部分。向下滚动以查看直接积累的文档。