У вас есть довольно простой набор условий, поэтому можно написать относительно простое правило для их проверки. Я рассмотрю каждое условие отдельно, а затем объединю их в окончательное правило.
Как вы писали:
есть по крайней мере один продукт, для которого 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