Drools检查列表中的一个属性是否存在于其他列表中

Drools检查列表中的一个属性是否存在于其他列表中,drools,business-rules,kie,drools-flow,Drools,Business Rules,Kie,Drools Flow,我得到以下结构: 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 c

我得到以下结构:

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; 
}

感谢您的帮助或建议

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

$productsToChecks : Product(customerId != "21") && type not in ("A", "B") from $products
您要检查的两个属性都需要位于
产品(…)
部件内部,如下所示:

$productsToChecks: Product( customerId != "21",
                            type not in ("A", "B")) from $products
在规则的其他部分也会重复此错误


因此,您的要求是:

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

我们可以将其提取为以下伪代码:

  • 什么时候
    • 产品不是:(类型=A或类型=B)且客户ID=21
    • (产品customerId==客户id)或(客户国家==空且产品国家==美国)
  • 那就做点什么
考虑到第二部分中的“或”,这是两条规则

我们需要做的第一部分是找到我们关心的产品子集。您可以通过多种方式来实现这一点--
收集
累积
是您立即想到的两种方法。假设问题中的要求是完整的,
collect
在这里更合适(也更简单)

现在,您可以使用该产品子集(不包括您需要忽略的产品)来匹配其他标准。正如我提到的,由于这些标准是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匹配且满足国家/地区要求,则产品可能会触发两次。)

但是,如果结果是满足条件的所有产品的列表,则可以再次使用函数获取该产品列表。在这种情况下,
累积
功能比
收集
功能更合适:

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
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
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