'from', 'accumulate' 和 'collect' 之间的关联<o:p></o:p>
作者: Mark Proctor <o:p></o:p>
在Drools4.0中,我们介绍了‘from’关键字,它允许你为模式声明一个推论的来源。这允许引擎使用不在Working Memory中的数据进行推论。源数据可能是绑定变量的子字段,或者方法调用的结果;后一种方式提供了与Hibernate集成的方法(通过调用命名的查询),Drools将把返回的结果与模式统一为一体。<o:p></o:p>
这里是一些简单的绑定子字段进行推论的例子:<o:p></o:p>
Person( personAddress : address )
address : Address( zc : zipcode == "23920W") from personAddress<o:p></o:p>
利用Drools引擎提供的新的表示方法带来的灵活性,你可以用很多办法来解决这个问题。下面是同样的结果,但是用“.”来实现。<o:p></o:p>
p : Person( )
address : Address( zc : zipcode == "23920W") from p.address<o:p></o:p>
当然,我们也可以使用新的表达式语言扩展来完成:<o:p></o:p>
Person( zc : address.zipCode == "2392OW")<o:p></o:p>
下一个例子举例如何在一个hibernate查询结果上进行推论,Restaurant模式将依次在每一个结果上进行推论和绑定。<o:p></o:p>
p : Person( )
Restaurant( food == p.favouriteFood )
from hs.getNamedQuery( "list restaurants by postcode" )
.setProperties( [ "postcode" : p.address.zipcode ] )
.list()<o:p></o:p>
'collect' 和 'accumulate' 在一个返回的对象上计算结果,这种模式可以指定‘from’作为它的源。'collect'允许对集合推论并且返回对象列表。'accumulate'允许对集合中每一个数据项执行操作,匹配给定模式并且执行操作返回用户选择的对象——通常用来求和或汇总数据,当然也可以用来做更复杂的工作。 <o:p></o:p>
<o:p> </o:p>
示例将两个from连在一起使用。它绑定所有购买的每样东西(item)的价值都超过10元的Customer(客户),items是Customer的字段,没有设置在Working Memory中。
c : Customer()
items : List( size == c.items.size )
from collect( Item( price > 10 ) from c.items )<o:p></o:p>
这里的List是从collect产生的,其中有size的属性。<o:p></o:p>
如果这里的items不是Customer的字段,但被设置到working memory中,我们可以使用一个相互关联的‘collect’模式。<o:p></o:p>
p : Customer ()
list : List()
from collect( Item( owner : p ) ) // 找到拥有者是p的所有Item
items : List(size == list.size)
from collect( Item( price > 10 ) from list )<o:p></o:p>
下面是如何使用'accumulate'达到同样的效果,它建立在'count'函数中;虽然这不与'from'举例关联,在这里将它做为一个补充。<o:p></o:p>
p : Person()
count : Number()
from accumulate( i : Item( owner == p ), count( i ) )
list : List( size == count )
from collect( Item( owner == p, price > 10 ) )<o:p></o:p>
对于更复杂的情况——深奥但是更具说明性,我们可以看下面的‘from’例子。对每一个Store(商店),购物的Person(顾客)有一个account(账目),我们返回Person在Store中所有购买的商品,并检查是否这些商品的价值平均超过50元的客户Person。<o:p></o:p>
p : Person()
s : Store( accountOwner == p )
a : Number( intValue > 50 )
from accumulate( item : Item( )
from collect( Item( store == s )
from hs.getNamedQuery( "get user items in store" )
.setProperties( [ "store" : s.name, "owner" : p.name ] )
.list() ),
average( item.price ) )<o:p></o:p>
因此对于那些Rete不能处理集合和嵌套或者working memory外的数据的说法,我希望这些可以让你改变想法。<o:p></o:p>
<o:p></o:p>
<o:p> </o:p>