2016-11-30 55 views
0

中使用子查詢我試圖從本質上定義一個總是最後(類似於CTL)使用Drools的查詢操作。樹由節點(稱爲Artifact)組成,用路徑標識符註釋。通過生成一個新的路徑ID並將事實SplitFrom(child, parent)插入到知識庫中來表示樹中的每個分裂(具有多於一個孩子的父親)。Drools:在所有

本質上,我們想要查看從某個起始路徑ID開始,樹中所有路徑上是否存在給定的Artifact對象。我試圖O此如下所示:

query alwaysFinally(String $type, String $productName, long $parentPathId) 
    Artifact(type == $type, productName == $productName, pathId == $parentPathId) 
    or 
    forall(SplitFrom(parent == $parentPathId, $childPathId := child) 
     and 
     ?alwaysFinally($type, $productName, $childPathId;)) 
end 

不幸的是,這會導致以下錯誤:

java.lang.RuntimeException: Build Errors: 
Error Messages: 
Message [id=1, level=ERROR, path=edu/umn/crisys/sim/agent/cognition/futureworld/rules/process/antecedent/commonAntecedents.drl, line=47, column=0 
    text=[ERR 102] Line 47:6 mismatched input '?' in query] 
Message [id=2, level=ERROR, path=edu/umn/crisys/sim/agent/cognition/futureworld/rules/process/antecedent/commonAntecedents.drl, line=0, column=0 
    text=Parser returned a null Package] 
... 

我已經打了在許多不同的方式插入括號,但我不」我認爲這是真正的問題。如果我刪除and,並用逗號或換行符替換它,我得到以下錯誤:

java.lang.ClassCastException: org.drools.core.rule.QueryElement cannot be cast to org.drools.core.rule.Pattern 

    at org.drools.compiler.rule.builder.ForallBuilder.build(ForallBuilder.java:57) 
    at org.drools.compiler.rule.builder.ForallBuilder.build(ForallBuilder.java:32) 
    at org.drools.compiler.rule.builder.GroupElementBuilder.build(GroupElementBuilder.java:66) 
    at org.drools.compiler.rule.builder.GroupElementBuilder.build(GroupElementBuilder.java:36) 
    at org.drools.compiler.rule.builder.GroupElementBuilder.build(GroupElementBuilder.java:66) 
    at org.drools.compiler.rule.builder.RuleBuilder.build(RuleBuilder.java:97) 
    at org.drools.compiler.builder.impl.KnowledgeBuilderImpl.addRule(KnowledgeBuilderImpl.java:1820) 
    at org.drools.compiler.builder.impl.KnowledgeBuilderImpl.compileRules(KnowledgeBuilderImpl.java:1111) 
    at org.drools.compiler.builder.impl.KnowledgeBuilderImpl.compileAllRules(KnowledgeBuilderImpl.java:989) 
    at org.drools.compiler.builder.impl.CompositeKnowledgeBuilderImpl.buildRules(CompositeKnowledgeBuilderImpl.java:260) 
    at org.drools.compiler.builder.impl.CompositeKnowledgeBuilderImpl.buildPackages(CompositeKnowledgeBuilderImpl.java:121) 
    at org.drools.compiler.builder.impl.CompositeKnowledgeBuilderImpl.build(CompositeKnowledgeBuilderImpl.java:105) 
    at org.drools.compiler.kie.builder.impl.AbstractKieModule.buildKnowledgePackages(AbstractKieModule.java:243) 
    at org.drools.compiler.kie.builder.impl.AbstractKieProject.verify(AbstractKieProject.java:64) 
    at org.drools.compiler.kie.builder.impl.KieBuilderImpl.buildKieProject(KieBuilderImpl.java:230) 
    at org.drools.compiler.kie.builder.impl.KieBuilderImpl.buildAll(KieBuilderImpl.java:198) 

我不認爲蓄電池會在這裏工作,因爲查詢是不是一個Pattern對象。

有沒有人有如何在Drools中表達這個好主意?

回答

0

你不需要所有的東西。這是Drools爲所有匹配自動執行的事情,以繼續匹配過程。因爲條件不一定適用於所有的事實,因此這裏是你不需要的通用量詞。

query alwaysFinally(String $type, String $productName, long $parentPathId) 
    Artifact(type == $type, productName == $productName, pathId == $parentPathId) 
    or 
    (SplitFrom(parent == $parentPathId, $childPathId := child) 
    and 
    ?alwaysFinally($type, $productName, $childPathId;) 
end 

如果工件出現多次,可能會導致多次匹配。

+0

也許我misexplained。當我運行它時,就像「or」的後半部分表示:如果有給定父級的splitFrom的子路徑,並且子路徑總是最終包含工件,則返回true。換句話說,它的行爲就像是存在量化的。我想要的是對於給定父項和每個子項路徑(或其路徑)中的所有splitFroms子項都包含該項目,然後返回true。我想過收集子路徑標識符,然後對這些標識符做一些嘗試,但是再次調用查詢就無法正常工作。 – desilvai

0

邏輯規則獲勝。 「或」聲明的後半部分可以表示爲(使用集合符號)

let childPathIds: { SplitFrom(parent == $parentPathId, child := childPathId } 
forall x in childPathIds, P(x) 

現在,我們可以雙重否定和保護身份。這得到我們:

let childPathIds: { SplitFrom(parent == $parentPathId, child := childPathId } 
exists x in childPathIds, not P(x) 

因此,它可以在使用dools表示以下

accumulate(SplitFrom(parent == $parentPathId, $childPathId := child); 
         $childPaths: collectSet($childPathId)) 
and 
// Set non-empty 
exists($childPathId: Long() from $childPaths) 
and 
(not(exists($childPathId: Long() from $childPaths 
     and 
     not (?alwaysFinally($type, $productName, $childPathId;)))) 
) 

注意附加非空的檢查?我們需要這樣做,因爲如果$childPaths爲空,則第三個條件將返回true。

因此,故事的寓意:是的,我們可以用子查詢來捕捉所有的東西;但是我們必須使用更加笨拙的語法才能做到這一點。至少我們不必深入Java來實現它。