【问题标题】:Drools iterate an object list and for all objects in the list, sum up the value of a field of the objectDrools 迭代一个对象列表,对于列表中的所有对象,求和该对象的某个字段的值
【发布时间】:2020-06-04 18:58:20
【问题描述】:

我正在尝试构建一个 drools 规则,其中提供的事实具有用户提供的 int 值。 Fact 还有一个具有预期 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 的总和。 有没有办法在流口水中做到这一点?任何帮助将不胜感激。

【问题讨论】:

  • 作为一种解决方法,我在 Order 类中添加了一个 expectedIntegrationFee 字段和 getExpectedIntegrationFee() 方法。此方法遍历所有包含的 OrderItem 对象及其对应的 Product 对象,并返回单个集成费用的总和。在我的 drools 规则中,然后我只需对照 usersIntegrationFee 检查预期的集成费用值。但我仍然想知道我是否可以在不改变我的事实类的情况下在流口水规则中做到这一切。
  • 无需解决方法。查看accumulate(在文档中向下滚动到“累积”;它在“收集”下方)
  • 只需阅读文档。这应该非常适合我的用例。谢谢!!!为什么不将您的评论复制到答案部分,以便其他人更容易寻找类似问题的答案,在那里找到它。
  • 我会看看我今天晚些时候是否有时间写一个答案。 :)

标签: list loops sum drools rules


【解决方案1】:

您需要使用一个名为accumulate 的drools 内置实用程序。此实用程序允许您在“累积”某种变量值的同时迭代右侧的对象集合。一些常见的用例涉及总和、均值、计数等。基本上,该构造循环遍历集合中的每个项目,并对每个项目执行一些定义的操作。

虽然您可以定义自己的自定义累加函数,但 Drools 支持多个内置累加函数 - 其中之一是 sum。这个内置函数是您的特定用例所需要的。

accumulate 的一般格式是这样的:accumulate( &lt;source pattern&gt;; &lt;functions&gt; [;&lt;constraints&gt;] )。您的规则看起来像这样(伪代码,因为我在这台计算机上没有 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 &gt; 0

关于我在此规则中选择的语法的最后说明。由于用例是“如果 usersIntegrationFee 小于总和则触发规则”,我将比较直接放在 Integer( ... ) from accumulate 中。当然,您可以单独进行比较,例如 Integer( $productFees &gt; this ) from $userFee 或您喜欢的任何其他比较格式。这种方式看起来最简单。

Drools documentation 包含有关此实用程序的更多信息。我已经链接到讨论“when”子句中的元素的部分;向下滚动一点可以直接查看累积的文档。

【讨论】:

    猜你喜欢
    • 2021-12-11
    • 2021-06-19
    • 2015-08-13
    • 2014-05-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多