在Drools中,memberOf / contains是否要求将测试对象明确地作为事实插入?

时间:2015-08-03 20:03:53

标签: drools

我仍然试图围绕一些流氓的基础知识。 我不明白的一件事是,我必须明确地将事实添加到会话中,而不是将事物声明为事实或(如何区别?)作为规则中的变量。

问题:我是否总是必须明确地添加一个事实,或者是否也将某个声明的变量视为一个事实?

说我有这个简化的层次结构:

public class Container {
    private Collection<Element> elements;
    // other stuff
}

public class Element {
    private SubElement subElement;
    // other stuff  
}

public class SubElement {
    private code;
    // other stuff
}

现在我想查找/匹配包含具有给定代码的SubElement的Elements的容器。 这是我创建的规则:

global Collection qualifyingCodes;
rule "container rule"
when
    // find a container 
    $container : Container( $elements : elements )

    // where there is an element within its elements list
    $element : Element(this memberOf $elements)

    // that has a sub element
    $subElement : SubElement(this == $element.subElement)

    // for which the code is in the (global) list of codes
    eval(qualifyingCodes.contains($subElement.code)) 
then
    ....

现在它似乎运行正常,但只有当我将容器,元素和子元素作为事实分别添加到我的会话中时。 我希望能够将容器对象添加为事实并由于&#34;声明&#34; $ elements / $ element / $ subElement drools也将这些理解为事实。 有没有办法做到这一点(或者我是否总是要扁平化我的数据结构并将其作为单独的事实添加)?

感谢您的任何建议!

1 个答案:

答案 0 :(得分:1)

作为事实插入的POJO可以与模式匹配,而无需建立上下文(正如您的规则所说明的那样)。

然而,可以创建一个上下文,其中可以或可能未作为事实插入的有限POJO集可以通过模式匹配:通过from短语。这里基本上是相同的规则,但没有Element和SubElement是事实:

rule "from rule"
when
  // find a container 
  $container : Container( $elements : elements )

  // where there is an element within its elements list
  $element : Element($subEl: subElement ) from $elements

  // that has a sub element
  $subElement : SubElement(this == $element.subElement, data == "DEF")
                from $subEl;
then
    System.out.println( "found Container " + $container +
                        " for " + $subElement.getData());
end

但是,除了在一般情况下可见之外,插入作为一个事实也有另一个结果:事实可以通过引擎知道该修改来修改。在“from rule”中,无法修改$ subElement,因此将SubElement的数据设置为“DEF”的任何修改都不会触发此规则(即使插入SubElement POJO也不会)。

为了完整起见:通过添加对父对象的引用,也简化了对象层次结构(组合)的推理,例如

rule "linkage rule"
when
    // a sub element GHI
    $subElement : SubElement( data == "GHI", $element: element)
then
    System.out.println( "found Container " + $element.getContainer() +
                        " for " + $subElement.getData());
end