注意:关于此主题,还有一个更好的问题。请投票关闭该投票。
我遇到了一个奇怪的案例,试图了解它为什么会发生。问题在于,规则在不断被触发,这是它的最后事实,而没有任何与之相关的变化。 我应该注意,我正在使用Drools 7.0.0
我有以下规则:
rule "TicketsBoughtPerClass"
when
$ticketClass : TicketClass($customer : customer)
accumulate(
Ticket
(
customer != null,
customer == $customer,
ticketPrice >= $ticketClass.startPriceRange,
ticketPrice <= $ticketClass.endPriceRange
);
$ticketCount : sum(1)
)
then
System.out.println("Total " + $ticketCount + " bought tickets for " + $ticketClass.getClassName());
insertLogical(new TotalTicketsBoughtForClass($ticketClass, $ticketCount));
end
rule "TicketsNeededForBonus"
when
$ticketClass : TicketClass($minTicketsNeededForBonus : minTicketsNeededForBonus)
TotalTicketsBoughtForClass(ticketClass == $ticketClass, ticketCount < $minTicketsNeededForBonus, $ticketCount : ticketCount)
then
//Do something based on ($minTicketsNeededForBonus - $ticketCount)
end
该想法是计算Ticket
的价格在TicketClass
范围内的Customer
个对象的数量。但是,正如我提到的,无论Ticket
的价格如何,最后插入的事实始终有一个规则触发器。
我为感兴趣的触发器添加了<- no match
。
以下是示例输出:
Ticket classes (inserting ticketClass facts):
First class - Start price range: 200, End price range: 300
Second class - Start price range: 100, End price range: 199
Third class - Start price range: 50, End price range: 99
Buying tickets:
Bought ticket #0 for 60$ (insert)
Bought ticket #1 for 199$ (insert)
Bought ticket #2 for 250$ (insert)
Calling initial fireAllRules()
Total 1 bought tickets for Third class
Total 1 bought tickets for Second class
Total 1 bought tickets for First class
Changed ticket #0 from 60$ to 168$ (update)
fireAllRules() called
Total 0 bought tickets for Third class
Total 2 bought tickets for Second class
Changed ticket #0 from 168$ to 233$ (update)
fireAllRules() called
Total 0 bought tickets for Third class <- no match
Total 1 bought tickets for Second class
Total 2 bought tickets for First class
Changed ticket #0 from 233$ to 230$ (update)
fireAllRules() called
Total 0 bought tickets for Third class <- no match
Total 2 bought tickets for First class
Changed ticket #0 from 230$ to 283$ (update)
fireAllRules() called
Total 0 bought tickets for Third class <- no match
Total 2 bought tickets for First class
Changed ticket #0 from 283$ to 167$ (update)
fireAllRules() called
Total 0 bought tickets for Third class <- no match
Total 2 bought tickets for Second class
Total 1 bought tickets for First class
Changed ticket #0 from 167$ to 24$ (update)
fireAllRules() called
Total 0 bought tickets for Third class <- no match
Total 1 bought tickets for Second class
Changed ticket #0 from 24$ to 1$ (update)
fireAllRules() called
Total 0 bought tickets for Third class <- no match
Changed ticket #0 from 1$ to 0$ (update)
fireAllRules() called
Total 0 bought tickets for Third class <- no match
Changed ticket #0 from 0$ to 8$ (update)
fireAllRules() called
Total 0 bought tickets for Third class <- no match
Changed ticket #0 from 8$ to 40$ (update)
fireAllRules() called
Total 0 bought tickets for Third class <- no match
除非我有误解,否则不应该。
我决定更深入地研究流口水的核心,以获得自己的答案。搜索使我对PhreakAccumulateNode.doRightUpdates
的累计节点中更新的元组进行了评估,这似乎是来自此附加触发器的地方。在方法doRightUpdatesProcessChildren
之前,存在以下代码:
// if LeftTupleMemory is empty, there are no matches to modify
if ( leftTuple != null ) {
if ( leftTuple.getStagedType() == LeftTuple.NONE ) {
trgLeftTuples.addUpdate( leftTuple ); //<----
}
doRightUpdatesProcessChildren( ARGS );
}
简而言之,这段代码总是将AccmulateMemory
中的第一个左元组添加为更新的,即使它没有更新,这也是导致RuleTerminalNode
始终触发的原因。元组。
我目前的困境是我不知道对trgLeftTuples.addUpdate( leftTuple )
的调用是否是故意完成的,因为当我查看PhreakJoinNode
中的代码时,处理时会出现极其相似的代码更新的元组,但是在调用doRightUpdatesProcessChildren
之前缺少此调用。
我对此有一个主要问题,如果这是预期的行为,如果是,为什么?。
答案 0 :(得分:1)
如果我做对了,并且您想消除没有规则的单据的情况下的规则触发,那么您应该添加其他约束。
rule "TicketsBoughtPerClass"
when
$ticketClass : TicketClass($customer : customer)
accumulate(
Ticket
(
customer != null,
customer == $customer,
ticketPrice >= $ticketClass.startPriceRange,
ticketPrice <= $ticketClass.endPriceRange
);
$ticketCount : sum(1);
$ticketCount > 0
)
then
System.out.println("Total " + $ticketCount + " bought tickets for " + $ticketClass.getClass().getName());
end
没有$ticketCount > 0
约束,您只有触发规则TicketClass()
的约束