累积引发不必要的规则后果

时间:2020-06-26 14:08:11

标签: drools

注意:关于此主题,还有一个更好的问题。请投票关闭该投票。

Link to new question

我遇到了一个奇怪的案例,试图了解它为什么会发生。问题在于,规则在不断被触发,这是它的最后事实,而没有任何与之相关的变化。 我应该注意,我正在使用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之前缺少此调用。

我对此有一个主要问题,如果这是预期的行为,如果是,为什么?

1 个答案:

答案 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()的约束

相关问题