查询是在工作内存中搜索符合所述条件的事实的简单方法。因此,它只包含规则的LHS结构,因此既不指定“when”也不指定“then”。查询具有一组可选参数,每个参数都可以选择键入。如果未给出类型,则假定为Object类型。Drools引擎将尝试根据需要强制执行值。查询名称是KieBase的全局名称; 所以不要将相同名称的查询添加到同一RuleBase的不同包中。
要返回结果,请使用ksession.getQueryResults("name")
“name”作为查询的名称。这将返回一个查询结果列表,允许您检索与查询匹配的对象。
第一个示例为30岁以上的所有人提供简单查询。第二个示例使用参数将年龄限制与位置相结合。
query "people over the age of 30"
person : Person( age > 30 )
end
query "people over the age of x" (int x, String y)
person : Person( age > x, location == y )
end
我们使用标准的“for”循环遍历返回的QueryResults。每个元素都是QueryResultsRow,我们可以使用它来访问元组中的每个列。可以通过绑定声明名称或索引位置访问这些列。
QueryResults results = ksession.getQueryResults( "people over the age of 30" );
System.out.println( "we have " + results.size() + " people over the age of 30" );
System.out.println( "These people are are over 30:" );
for ( QueryResultsRow row : results ) {
Person person = ( Person ) row.get( "person" );
System.out.println( person.getName() + "\n" );
}
为更紧凑的代码添加了对位置语法的支持。默认情况下,类型声明中声明的类型顺序与参数位置匹配。但是可以使用@position注释覆盖它们。这允许模式与位置参数一起使用,而不是更详细的命名参数。
declare Cheese
name : String @position(1)
shop : String @position(2)
price : int @position(0)
end
org.drools.definition.type包中的@Position注释可用于在类路径上注释原始pojos。目前,只能对类上的字段进行注释。支持类的继承,但不支持接口或方法。下面的isContainedIn查询演示了在模式中使用位置参数; Location(x, y;)
代替Location( thing == x, location == y).
查询现在可以调用其他查询,这与可选的查询参数相结合,提供了派生查询样式的反向链接。参数支持位置和命名语法。也可以混合位置和命名,但位置必须首先,由分号分隔。文字表达式可以作为查询参数传递,但在此阶段您不能将表达式与变量混合。以下是调用另一个查询的查询示例。请注意,此处的“z”始终为“out”变量。'?' 符号表示查询仅为拉取,一旦返回结果,您将无法在基础数据更改时收到进一步的结果。
declare Location
thing : String
location : String
end
query isContainedIn( String x, String y )
Location(x, y;)
or
( Location(z, y;) and ?isContainedIn(x, z;) )
end
如前所述,您可以使用实时“开放”查询来反复接收查询结果随时间的变化,因为它查询的基础数据会发生变化。请注意,“look”规则在不使用“?”的情况下调用查询。
query isContainedIn( String x, String y )
Location(x, y;)
or
( Location(z, y;) and isContainedIn(x, z;) )
end
rule look when
Person( $l : likes )
isContainedIn( $l, 'office'; )
then
insertLogical( $l 'is in the office' );
end
Drools支持派生查询的统一,简而言之,这意味着参数是可选的。可以使用静态字段org.drools.core.runtime.rule.Variable.v从Java调用查询而不指定参数 - 请注意,您必须使用'v'而不是Variable的替代实例。这些被称为'out'参数。请注意,查询本身不会在编译时声明参数是进入还是出现,这可以在每次使用时纯粹在运行时定义。以下示例将返回office中包含的所有对象。
results = ksession.getQueryResults( "isContainedIn", new Object[] { Variable.v, "office" } );
l = new ArrayList<List<String>>();
for ( QueryResultsRow r : results ) {
l.add( Arrays.asList( new String[] { (String) r.get( "x" ), (String) r.get( "y" ) } ) );
}
该算法使用堆栈来处理递归,因此方法堆栈不会爆炸。
也可以使用查询的输入参数作为fact的字段,如:
query contains(String $s, String $c)
$s := String( this.contains( $c ) )
end
rule PersonNamesWithA when
$p : Person()
contains( $p.name, "a"; )
then
end
以及更多通常的任何类型的有效表达式,如:
query checkLength(String $s, int $l)
$s := String( length == $l )
end
rule CheckPersonNameLength
when
$i : Integer()
$p : Person()
checkLength( $p.name, 1 + $i + $p.age; )
then
end
以下内容尚不支持:
-
List and Map统一
-
表达统一 - pred(X,X + 1,X * Y / 7)