我对 Drools 还很陌生,但想将它用于我需要解决的案例。
基本上我的规则需要执行以下操作:
- 根据到人员当前位置的给定距离过滤给定的初始只读(完整)位置列表
- 创建一个新列表,其中包含给定距离半径内的位置
- 将新列表移交给下一条规则
- 根据特定标题过滤新位置列表
- 创建包含位置的新列表(现在按距离和标题进行过滤)
所以,我想链接几个规则...首先这样做,创建包含结果的新列表,在下一个规则中使用新列表,对其执行进一步过滤,创建包含更多过滤元素的新列表...等等在...
老实说,正如之前提到的,我完全陷入困境,并认为我可以获得一些建议......
我想出的最初规则如下:
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 端时,我可以从工作内存中获取所有列表并用它们做进一步的事情。
是的,我知道,我的问题可能非常n00b-ish......但我找不到任何可以从中得出我的用例的东西。
但是,提前致谢。
最佳答案
我将逐点解决这个问题,而不是尝试提供“完整”的解决方案。您必须决定使用什么。
首先,将所有位置保留在作为单个事实的容器类中可能有充分的理由,但通常,如果容器元素本身就是事实,则规则更容易编写。
rule "person and location"
when
$p: Person()
$l: TopLocation(...)
...
(当然,您可以坚持使用 from
子句。)
要选择具有特定属性与人员组合的位置:使用任何 boolean 表达式作为约束或评估模式。如果表达式涉及某些静态 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" )
...
等等。
您会说此规则仅适用于单个选择用例 - 如果距离不同或者您正在寻找书店怎么办?
您可以使用参数 block 事实来定义文字。
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
现在可以轻松地任意选择条件,并使用从当前搜索派生的值。 - 您可以在 fireAllRules
返回后使用 API 检索 ResultSet
,或者编写另一个规则来处理和收回它。
我建议您研究现有文献。
关于java - Newbee Drools 链表过滤,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35493798/