Drools сравнивают, если один список содержит элемент из другого списка

У меня есть структура на Java:

public class Request {
  List<Product> product;
  List<Account> accounts;
}

public class Product {
 String productIdOne;
 String productIdTwo;
 String productTax;
}  


public class Account {
  List<ProductRelationship> productsRelationship;
}
public class ProductRelationship {
  String productIdOne;
  String productIdTwo;
}

А запрос - это факт, отправляемый слюнявым. Мне интересно, как я могу проверить, есть ли хотя бы один продукт, для которого для productTax установлено значение «true», и существует ли связь между одной учетной записью и одним продуктом. Другими словами, если существует продукт с налоговым значением true и хотя бы одна учетная запись содержит связь с этим продуктом (по productIdOne и productIdTwo), то результат правила должен пройти;

Основная проблема заключается в том, что список взаимосвязей продуктов находится внутри списка учетных записей.

Спасибо за любой совет


person Łukasz Woźniczka    schedule 06.07.2020    source источник


Ответы (2)


У вас есть довольно простой набор условий, поэтому можно написать относительно простое правило для их проверки. Я рассмотрю каждое условие отдельно, а затем объединю их в окончательное правило.

Как вы писали:

есть по крайней мере один продукт, для которого productTax имеет значение "true"

Теперь, как вы упомянули, ваши входные данные правила - это экземпляр Request, который содержит два списка (продукты, учетные записи). Мы начнем с объявления, что:

rule "Account exists with taxed product"
when
  Request( $products: product != null, 
           $accounts: accounts != null )

Далее мы хотим найти облагаемый налогом продукт. Если бы мы только хотели доказать существование продукта, мы могли бы использовать exists( ... ) условие, что очень быстро. Однако, поскольку мы хотим провести дальнейшие сравнения, мы хотим действительно найти продукт с этим условием и сохранить ссылку на него.

$taxedProduct: Product( productTax == "true" ) from $products

Я предположил, что любое значение, отличное от истинного, указывает на не облагаемый налогом продукт. Вы должны отрегулировать по мере необходимости (и, возможно, подумайте об изменении этого типа на логическое).

Следующее условие - найти аккаунт:

существует связь между одним аккаунтом и [облагаемым налогом] продуктом

Во-первых, нам нужно обновить наше объявление $taxedProduct и получить ссылки на его идентификаторы:

$taxedProduct: Product( productTax == "true",
                        $id1: productIdOne,
                        $id2: productIdTwo ) from $products

Теперь нам нужно найти учетную запись с соответствующими отношениями.

$account: Account( $relationships: productsRelationship != null ) from $accounts
exists( ProductRelationship( productIdOne == $id1,
                             productIdTwo == $id2 ) from $relationships )

Здесь я использовал exists условие для отношения, потому что нам больше не нужно ссылаться на саму связь, просто убедитесь, что связь существует. Я объявил переменную $account, чтобы указать на учетную запись, имеющую отношение к продукту.

Собирая все вместе, мы получаем:

rule "Account exists with taxed product"
when
  Request( $products: product != null, 
           $accounts: accounts != null )
           
  $taxedProduct: Product( productTax == "true",
                          $id1: productIdOne,
                          $id2: productIdTwo ) from $products

  $account: Account( $relationships: productsRelationship != null ) from $accounts
  exists( ProductRelationship( productIdOne == $id1,
                               productIdTwo == $id2 ) from $relationships )
then
  // We have a taxed product $taxedProduct
  // and an associated account $account
end

Когда я впервые начал работать с Drools, мне было трудно понять, как он обрабатывает объекты в списках, поэтому подсписок ProductRelationship кажется сложной проблемой на первый взгляд. Что Drools собирается сделать, так это перебрать список $ products и найти те экземпляры Product, которые соответствуют нашим критериям (а именно, имеют productTax == "true".). После того, как он обнаружит эти облагаемые налогом продукты, он аналогичным образом просматривает список $ accounts и находит все Accounts. которые соответствуют критериям (у которых есть список productsRelationship). Затем для каждой из этих учетных записей он собирается проверить, существует ли связь, как мы определили.

Это, конечно, упрощенное объяснение, но оно помогает сформировать мысленную модель примерно того, что здесь делает Drools. На самом деле Drools намного эффективнее, чем рабочий процесс примерно O (n ^ 3), который я только что описал.

Следует иметь в виду, что это правило не прекращается, как только оно находит совпадение. Если у вас есть два облагаемых налогом продукта, которые связаны с одной учетной записью, это правило сработает дважды - по одному разу для каждого облагаемого налогом продукта. Или, в качестве альтернативы, если у вас есть один облагаемый налогом продукт и две учетные записи, которые связаны с ним, правило будет срабатывать дважды (один раз для каждой учетной записи). Как правило, правило срабатывает один раз для каждого совпадения, которое оно находит в данном запросе.

person Roddy of the Frozen Peas    schedule 07.07.2020

Вы можете попробовать следующее

 rule "sample"
  no-loop
   

      when
         request:Request(accountList: accounts)
         request1:Request(productList: product)
         Account(productsRelationshipList:ProductRelationship) from accountList
         Product(productId contains productsRelationshipList, productTax = true ) from  productList
      then
          System.out.println("Rule fired satisfied");
      end
person Thilakar Raj    schedule 06.07.2020