流口水查询。他们是如何评估和执行的?

Drools Queries. How are they evaluated and executed?

我正在概念验证应用程序中评估 Drools 6。我要么误解了 Drools 中的查询是如何工作的,要么我没有正确实施某些东西。有人可以向我解释这种行为吗:

我有一个规则应该像这样作用于经过验证的记录:

rule "Patient Intake: Valid new Patients without a Medical History require a Review"
    ruleflow-group "Patient Intake"
    when
        $patient : Patient( status == PatientStatus.NEW )
        not Invalid( value == $patient )
    then
        modify( $patient ){
            setStatus( PatientStatus.PENDING_REVIEW )
        };

        insert( new Valid( $patient ) );
    end

query "Intake Results"
    Valid( $patients : value )
end

Valid/Invalid对象的使用就像使用特征一样,但是文档表明特征特征仍然experimental/subject可以改变,所以我暂时选择了这个替代方案。我认为查询很简单。我正在使用无状态会话并像决策服务一样调用引擎。以下代码片段显示了如何调用引擎(目前一些值是硬编码的):

StatelessKieSession kSession = kContainer.newStatelessKieSession( "TestKSession" );
KieRuntimeLogger auditLog = KieServices.Factory.get().getLoggers().newFileLogger( kSession, "audit" );
kSession.setGlobal( "logger", logger );

List<Command> commands = new ArrayList<Command>();
commands.add( CommandFactory.newInsertElements( request.getAllFacts() ) );
commands.add( CommandFactory.newQuery( "$patients", "Intake Results" ) );
commands.add( CommandFactory.newStartProcess( "x.y.z.intake" );

ExecutionResults results = kSession.execute( CommandFactory.newBatchExecution( commands ) );
auditLog.close();

我这样处理结果:

    private void processResults( ExecutionResults results ) {
        QueryResults qr = (QueryResults) results.getValue( "$patients" );
        for ( QueryResultsRow row : qr ) {
            // ... this code is never executed
        }
}

在控制台中,我看到 println 语句表明 QueryResult 大小为 0。但是,如果我将查询更改为仅收集 $patients : Object(),则 QueryResult 大小是通过 CommandFactory 插入的对象数,并且不包括作为规则 RHS 的一部分插入的对象。当我检查审计日志时,我发现确实插入了一个类型为 Valid 的对象。

为什么我的查询没有返回预期的结果?我是不是执行错了什么,或者我只是误解了查询的工作原理?

谢谢, 詹姆斯

添加命令的顺序很重要。添加查询命令是向引擎发出执行该查询的信号,因此在进程启动之前插入事实和查询运行。

反转添加查询和启动进程的行是关键。现在应该是:

List<Command> commands = new ArrayList<Command>();
commands.add( CommandFactory.newInsertElements( request.getAllFacts() ) );
commands.add( CommandFactory.newStartProcess( "x.y.z.intake" );
commands.add( CommandFactory.newQuery( "$patients", "Intake Results" ) );