Search code examples
javadrools

Drools "join" like SQL in collect


So I something like SQL join possible in drools. I have ItemFact collection (1,2,3,...), each item may be used in different baskets. I have CanUseItemInBasket facts, that represents if item can be used in basket or no

I have tried this

rule "xxx"
    when
        $beers : ArrayList() from collect( ItemFact(id == $orderItemId )
                             from collect(CanUseItemInBasket($itemId: orderItemId, basketId == 5)))
    then
    ...
end

or this

rule "xxx"
    when
        $beers : ArrayList() from collect( ItemFact(id == $orderItemId ), CanUseItemInBasket($itemId: orderItemId, basketId == 5))
    then
    ...
end

but this approaches not work. I know I add field basketId to ItemFact and add multiple ItemFacts with the same id and different basketIds, but in this approach ItemFact is "cloned" in working memory


Solution

  • To collect the ItemFact instances whose id is in the selected CanUseItemInBasket instances you can use accumulate:

    rule "Collect beers"
    when
        $beers : List() from accumulate(CanUseItemInBasket($itemId: orderItemId, basketId == 5) and
                                        $item: ItemFact(id == $itemId);
                                        collectList($item))
    then
        System.out.println($beers);
    end
    

    The v6.x language reference says:

    The Conditional Element accumulate is a more flexible and powerful form of collect, in the sense that it can be used to do what collect does and also achieve results that the CE collect is not capable of achieving.

    A similar note is in v7.x, and v8.x lists collect among obsolete keywords.