Newbee Drools链式列表过滤

时间:2016-02-18 22:32:18

标签: java drools rule-engine

我对Drools很新,但想把它用于我需要解决的案例。

基本上我的规则需要执行以下操作:

  • 根据与当前位置的给定距离过滤给定的初始只读(完整)位置列表
  • 创建一个包含指定距离半径内位置的新列表
  • 将新列表移交给下一个规则
  • 根据特定标题过滤新位置列表
  • 创建一个包含位置的新列表(现在按距离和标题过滤)

所以,我想链接几个规则...首先要这样做,创建包含结果的新列表,在下一个规则中使用新列表,对其执行进一步过滤,创建具有更多过滤元素的新列表......等等在......

老实说,如前所述,我完全被困住了,以为我可以得到一些adivsory ......

我想出的最初规则是这样的:

package com.acme.rulesets
import com.acme.domain.TopLocation
import com.acme.domain.Person
import com.acme.storage.LocationContainer
import com.acme.helper.GeoHelpers
rule "Get by Distance"
salience 10
when
    $allLocations: LocationContainer()
    $person: Person()
    $loc: TopLocation() from $allLocations.getAllLocations()
then
    double distance = GeoHelpers.getInstance().getHaversineInMiles($person.getLat(), $person.getLon(), $loc.getLat(), $loc.getLon());
    System.out.println($loc.getTitle() + " -- distance in miles to person: " + distance); 
end;

它没有 - 到目前为止 - 我想要实现的目标......但也许你可以给出一些提示......

所以,首先我认为我需要在规则的LHS中调用我的静态java方法(它只计算两个给定点之间的距离),但是一旦我(尝试)这样做,它就会编译规则失败。然后我需要使用$ dist的结果来确定,如果当前条目需要放入新列表(我怎么能a。)创建一个新列表,然后b。)将当前条目放入其中?)..然后,下一个逻辑步骤是创建一个具有更高显着性的新规则“按位置标题获取”并使用新的过滤列表。所以最后,当我回到java端时,我可以从工作记忆中获取所有列表,并用它们做更多的事情。

是的,我知道,我的问题可能非常糟糕......但我找不到任何可以从中得出用例的内容。

但是,提前谢谢。

1 个答案:

答案 0 :(得分:1)

我将逐点解决这个问题,而不是尝试提供“完整”的解决方案。你必须决定使用什么。

首先,可能有充分的理由将容器类中的所有位置保留为单一事实,但通常,如果容器元素本身是事实,则规则更容易编写。

rule "person and location"
when
    $p: Person()
    $l: TopLocation(...)
    ...

(当然,你可以坚持from条款。)

要选择具有特定属性的位置以及Person:使用任何布尔表达式作为约束或eval模式。如果表达式涉及一些静态Java函数,则将其导入(就像在Java中一样)或将其实现为DRL函数。我将把它说明为三者的组合。

import com.acme.helper.GeoHelpers
function double dist( Person p, TopLocation t ){
    double d =
      GeoHelpers.getInstance().getHaversineInMiles(p.getLat(), p.getLon(),
                                                   t.getLat(), t.getLon());
}

rule "p & l closer than"
when
    $p: Person()
    $l: TopLocation( dist($p,$l) < 100.0 )
    ...

要按更多条件过滤地点,您可以使用附加规则,其中选择了符合所需“标题”的位置,但这需要跟踪按距离选择的位置。要做到这一点,只需在规则中添加“标题”约束:

 rule "p & l: Hotel closer than 100"
 when
    $p: Person()
    $l: TopLocation( dist($p,$l) < 100.0,
                     title == "Hotel" )
    ...

等等。

你会说这个规则仅适用于单个选择用例 - 如果距离不同或者你正在寻找书店怎么办?

您可以使用参数块事实来定义文字。

rule "p & l, X loc closer than D"
when
    Param( $d: distance, $t: title )
    $p: Person()
    $l: TopLocation( dist($p,$l) < $d, title == $t )
    ...

你可能会说这很好但是如果选择标准本身的组合变化,而不仅仅是值?然后,当然,拥有单独的规则可能确实更好,每个规则都按单个标准选择位置。有了这个,提供参数可以与选择适当的规则相结合,这可以由多个Param子类完成。还会出现另一个问题:如何跟踪选择集。为此,我们可能必须使用另一个辅助事实,我们称之为ResultSet。假设距离始终是一个标准,我们可以编写诸如

之类的规则
rule "p & l, closer than D"
when
    $dp: DistParam( $v: distance )
    $p: Person()
    $l: ArrayList() from 
        collect( $l: TopLocation( dist($p,$l) < $v )
then
    retract( $dp );
    insert( new ResultSet( $l ) );
end

rule "p & l, filter by title"
when
    $t: TitleParam( $v: title )
    $r: ResultSet( $s: result )
    $l: ArrayList() from 
        collect( $l: TopLocation( title == $v ) from $s
then
    retract( $t );
    modify( $r ){ setResult($l) }
end

现在很容易有一个任意选择的标准,其值来自当前搜索。 - 您可以在ResultSet返回后使用API​​检索fireAllRules,或者编写其他规则来处理和撤消。

我建议您研究现有文献。