【问题标题】:Drools check if one property from list is present in other listDrools 检查列表中的一个属性是否存在于另一个列表中
【发布时间】:2021-02-11 19:09:12
【问题描述】:

我有以下结构:

public class Proposal {
   private final List<Product> products; 
   private final List<Customer> customers;
}

public class Customer {
   private String id;
   private String country;
}

public class Product {
  private String customerId;
  private String country;
  private String type; 
}

要求是: 不要检查产品类型是“A”还是“B”,对于 id 为 21 的客户。 对于任何其他产品,请检查 customerId 是否与 id 匹配,或者客户国家/地区是否设置为 null 并且产品上的国家/地区是否设置为“美国”

基于此,我准备了一条规则,但它没有按应有的方式工作:

//rule body
Proposal($products: products, $customers: customers)

$productsToChecks : Product(customerId != "21") && type not in ("A", "B") from $products

//first condition to check if there is any applicable case:
exist(Product(customerId != "21") && type not in ("A", "B") from $products) and

(
  // check if there is a customer who can use this product
  forall (
    Product($customerId: customerId, $country: country) from $productsToChecks
    Customer(id == $customerId || (country == null &&  $country == "US"))

  )
)

感谢您的任何帮助或建议

【问题讨论】:

    标签: drools business-rules kie drools-flow


    【解决方案1】:

    您的$productsToChecks 声明中有语法错误:

    $productsToChecks : Product(customerId != "21") && type not in ("A", "B") from $products
    

    您要检查的两个属性都需要在 Product( ... ) 部分中,如下所示:

    $productsToChecks: Product( customerId != "21",
                                type not in ("A", "B")) from $products
    

    您在规则的其他部分也重复此错误。


    所以你的要求是:

    不要检查产品类型是“A”还是“B”以及客户 ID 为 21。对于任何其他产品,请检查 customerId 是否与 id 匹配,或者客户国家/地区是否设置为 null 并且国家/地区是否打开产品设置为“美国”

    我们可以把它提炼成下面的伪代码:

    • 何时
      • 产品不是:(type=A 或 type=B)且 customerId=21
      • (产品 customerId == 客户 ID)或(客户国家/地区 == null 和产品国家/地区 == 美国)
    • 那就做点什么

    鉴于第二部分中的“或”,这是两条规则。

    我们需要做的第一部分是找到我们关心的产品子集。您可以通过多种方式做到这一点——collectaccumulate 是立即浮现在脑海中的两个。假设您问题中的要求是完整的,collect 在这里更合适(也更简单)。

    Proposal($products: products, $customers: customers)
    
    $productSubset: List() from collect( Product( customerId != 21, type not in ("A", "B") ) from $products)
    

    现在您可以使用该产品子集(不包括您需要忽略的产品)来匹配您的其他条件。正如我所提到的,由于这些标准是 OR'd,它们应该是两个不同的规则。

    rule "Product customerId matches Customer id"
    when
      Proposal($products: products, $customers: customers)
      $productSubset: List() 
                      from collect( Product( customerId != 21, type not in ("A", "B") ) from $products)
    
      Customer( $id: id != null ) from $customers
      $product: Product( customerId == $id ) from $productSubset
    then
      // do something with $product
    end
    
    rule "US Product and no Customer Country"
    when
      Proposal($products: products, $customers: customers)
      $productSubset: List() 
                      from collect( Product( customerId != 21, type not in ("A", "B") ) from $products)
    
      Customer( country == null ) from $customers
      $product: Product( country == "US" ) from $productSubset
    then
      // do something with $product
    end
    

    要减少重复代码,您可以将常用条件提取到单个“父”规则中,然后使用 extends 关键字创建两个具有不同条件的子规则。

    我以这种方式设计这些规则是在假设您希望对符合您的标准的每个产品执行一些操作的情况下设计的。基于此假设,右侧将针对每个符合每个规则的条件的产品触发(另请注意,由于这两个规则不是互斥的,如果 customerId 匹配 满足国家/地区要求。)

    但是,如果您想要的结果只是满足条件的所有产品的列表,您可以再次使用函数来获取该产品列表。在这种情况下,accumulate 函数比collect 更合适:

    rule "Get list of products for customer"
    when
      Proposal($products: products, $customers: customers)
      $productSubset: List() 
                      from collect( Product( customerId != 21, type not in ("A", "B") ) from $products)
    
      Customer( $id: id != null, $country: country ) from $customers
    
      $product: Product( customerId == $id ) from $productSubset
    
      $customerProducts: List() from accumulate(
                           $p: Product((customerId == $id) || ($country == null && country == "US")) from $products,
                           collectList($p)
                         )
    then
      // do something with $customerProducts
    end
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-06
      • 2013-12-12
      • 2021-09-19
      • 2012-10-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多