尝试在Drools中收集嵌套列表时出现问题

时间:2016-10-17 08:28:16

标签: drools

我在尝试用Drools(6.4.Final)编写规则时遇到了一些困难。 要么我的规则不完全正确,要么我最终为同一目标编写了几条规则但没有信念。我希望根据您的经验和/或参考资料获得您的意见,以帮助我。

我有一个事实(类型C),其中包含一个E.

列表

每个E:

  • 的int属性为年
  • 可能有一个R
  • 列表

每个R:

  • 有一个类型
  • 有金额

我想检查一年/每年是否某种类型的R的金额总和超过一个值。 如果它超过了,我想插入一个事实(X)与后面的所有E。

我的第一次尝试是

# Realm Object Server Configuration
#
# For each possible setting, the commented out values are the default values
# unless another default is mentioned explicitly.
#
# Paths specified in this file can be either absolute or relative.
# Relative paths are relative to the current working directory.

auth:
  ## The path to the public and private keys (in PEM format) that will be used
  ## to validate identity tokens sent by clients.
  ## These configuration options are MANDATORY.
  public_key_path: /etc/realm/token-signature.pub
  private_key_path: /etc/realm/token-signature.key

  providers:
    ## Providers of authentication tokens. Each provider has a configuration
    ## object associated with it. If a provider is included here and its
    ## configuration is valid, it will be enabled.

    ## Possible providers: cloudkit, debug, facebook, realm, password
    ## Providers 'realm' and 'password' are always enabled:
    ## - The 'realm' provider is used to derive access tokens from a refresh token.
    ## - The 'password' provider is required for the dashboard to work. It supports
    ##   authentication through username/password and uses a PBKDF2 implementation.

    ## This enables authentication via a Google Sign-In access token for a
    ## specific app.
    google:
      ## The client ID as retrieved when setting up the app in the Google
      ## Developer Console.
      clientId: '<SOME-HASH-HERE>.apps.googleusercontent.com'

    ## This enables authentication via a Facebook access token for a specific app.
    ## This provider needs no configuration (uncommenting the next line enables it).
    facebook: {}

它正在运作,但X中的元素存在问题,可能没有任何R或R与期望类型不匹配...

我的第二次尝试是

几个但更简单的规则声明了一种类型,以帮助累积数据并使用单个E。

rule "Sum of R exceed for one year"
when
   C( $listOfE : listOfE )

// Pick one E
   E( $year : year ) from $listOfE

// All Es of the same year
// "collectLists" is a custom accumulate function that simply adds all the elements of a list
  accumulate ( E(year == $year, $listofR : listofR ) from $listOfE;
            $allR : collectLists($listofR))

  // Check the sum
  // "sumbd" is  a custom accumulate function that simply adds BigDecimal (sum is broken for that in 6.4)
  accumulate ( R( type == « X », $amount : amount ) from $allR;
               $sum : sumbd($amount);
               $cumulAnnee > 20000)

then
  insert( new X($year, $elements));
end

但是我对这个解决方案并不自信,看起来(非常)很复杂。 最后,我希望有一个易于理解和维护的简单规则。

由于

1 个答案:

答案 0 :(得分:1)

一种简单的方法是在一次通过中收集所有E和R的所有总和并返回Map<YearType,BigDecimal> YearType结合年份和类型,并且您可以提取Entry对象检查BigDecimal等等。

我不确定你是否可以编写一个返回Map的自定义累加函数,但是可以使用“传统”累积语法来完成,你可以使用init,action和result子句来编写你需要的任何东西。

这是您可能使用的累积版本的简短版本:

Map() from accumulate( E( $lr: listOfR != null, $y: year )
                       init( Map m = new HashMap(); )
                       action( for( int i = 0; i < $lr.size(); ++i ){
                                 //... add to m.get($y) observing R's type
                               } )
                       result( m ) )