2012-03-20 30 views
11

這可能很容易回答,但我甚至無法弄清楚如何制定Google查詢來找到它。如何在SPARQL構造查詢中遞歸地展開空白節點?

我正在寫包含空白節點的數據集的SPARQL構造查詢。所以,如果我不喜歡

CONSTRUCT {?x ?y ?z .} WHERE {?x ?y ?z .}

查詢然後我的結果之一可能是:

nm:John nm:owns _:Node

這是一個問題,如果所有的

_:Node nm:has nm:Hats

三元組也不會以某種方式進入查詢結果(因爲我使用的一些解析器就像rdf lib的Python真的不喜歡懸掛的bnodes)。

有沒有辦法寫我的原始CONSTRUCT查詢來遞歸地添加所有三元組附加到任何bnode結果,以便沒有bnodes留在我的新圖中懸掛?

+2

如果你的方式,你可以運行構造查詢,然後運行鍼對一個SPARQL查詢這樣做,你其實可以* *獲得使用SPARQL查詢簡潔有界描述(CBD)。看看[Sparql查詢以遞歸方式返回組成rdfs:類定義的所有三元組](http://answers.semanticweb.com/questions/26220/sparql-query-to-return-all-triples-recursively- (並且可能[在SPARQL中實現簡明有界描述](http://answers.semanticweb.com/questions/20361/implementing-concise-bounded-description-in-sparql) )。 – 2015-03-19 14:10:01

+1

在前面的評論中,答案背後的想法是你可以創建一個*新的屬性*,它有效地作爲屬性路徑中的謂詞。例如,對於每個IRI節點,您添加一個三重「i selfIRI i」。然後當你寫一個像「?x p/selfIRI?y」的路徑時,你已經確保?y是一個IRI節點。 – 2015-03-19 14:15:01

回答

10

遞歸是不可能的。我能想到的最接近的是SPARQL 1.1 property paths(注意:該版本已過時),但bnode測試不可用(afaik)。

你可以只取出聲明尾隨bnodes:

CONSTRUCT {?x ?y ?z .} WHERE 
{ 
    ?x ?y ?z . 
    FILTER (!isBlank(?z)) 
} 

或試試你的運氣獲取下一個位:

CONSTRUCT {?x ?y ?z . ?z ?w ?v } WHERE 
{ 
    ?x ?y ?z . 
    OPTIONAL { 
    ?z ?w ?v 
    FILTER (isBlank(?z) && !isBlank(?v)) 
    } 
} 

(即最後一個查詢是相當懲罰,順便說一句)

DESCRIBE可能會更好,這通常會跳過bnodes。

+0

感謝用戶。我目前的計劃是使用兩級查詢,而不用擔心遞歸更深入。 isBlank過濾器可能有所幫助,但FILTERs似乎確實在屠殺性能,因爲SPARQL似乎在逐行執行過濾器之前實現了整個預過濾器子圖。因此,除非未過濾的子圖很小,否則過濾器查詢會變得非常密集。 – rogueleaderr 2012-03-20 19:22:53

+2

您不能說「SPARQL正在實現整個預過濾器子圖......」:不同的SPARQL引擎實現將具有不同的算法,並具有不同的優缺點。它甚至取決於您使用的庫的版本。 – 2012-03-21 08:03:53

3

正如user205512建議的那樣,遞歸地執行這個抓取是不可能的,正如他們指出的那樣,使用可選的(s)將任意級別放入數據中,使得節點在除了非平凡大小的數據庫之外的其他任何東西上都不可行。

Bnode本身在本地範圍內,結果集或文件。無法保證從解析中獲得BNode,或者從結果集中得到的是與數據庫中使用的相同的ID(儘管某些數據庫確實保證了查詢結果)。此外,像「select?s where {?s?p _:bnodeid1}」這樣的查詢與「select?where {?s?p?o}」相同 - 請注意,在這種情況下,bnode被視爲變量,而不是「這個東西與身份證'bnodeid1'」這種設計的怪癖使得很難查詢Bnodes,所以如果你掌握了數據,我建議不要使用它們。爲原本可能是bnodes的東西生成名稱並不難,並且在查詢期間命名資源與bnodes不會增加開銷。

這不會幫助您減輕和獲取數據,但爲此,我不建議您執行此類常規查詢;它們不能很好地擴展並且通常返回比您想要或需要的更多。我建議你做更直接的查詢。您的原始構造查詢將拉下整個數據庫的內容,這通常不是您想要的。

最後,儘管描述可能有用,但沒有標準的實現; SPARQL規範沒有定義任何特定的行爲,所以它返回給數據庫供應商,它可能會有所不同。如果您計劃在您的應用程序中嘗試使用不同的數據庫,那麼這可以使您的代碼更加輕便。如果你想要描述一個特定的行爲,你最好自己實現它。爲資源做簡單有界的描述是一段簡單的代碼,儘管你可能會遇到一些Bnodes問題。

+1

謝謝你的答案邁克爾。我的示例查詢有點不準確......我試圖實際做的是提取出有關我下載的數據集中給定實體的所有信息。但是該數據集包括諸如「John是_:1234的創建者」之類的條目。所以我想我的選擇是使用兩級查詢,並希望它不會壓縮性能,或者只是重新命名數據庫來命名所有的bnode。它看起來像SPARQL規範可以使用更強大的支持,因爲這似乎並不是一個特別罕見的問題。 – rogueleaderr 2012-03-20 19:20:03

1

關於ruby RDF.rb庫的使用,它允許在RDF :: Graph對象上使用重要的便利方法進行SPARQL查詢,下面應該展開空白節點。

rdf_type = RDF::SCHEMA.Person # for example 
rdf.query([nil, RDF.type, rdf_type]).each_subject do |subject| 
    g = RDF::Graph.new 
    rdf.query([subject, nil, nil]) do |s,p,o| 
    g << [s,p,o] 
    g << rdf_expand_blank_nodes(o) if o.node? 
    end 
end 

def rdf_expand_blank_nodes(object) 
    g = RDF::Graph.new 
    if object.node? 
    rdf.query([object, nil, nil]) do |s,p,o| 
     g << [s,p,o] 
     g << rdf_expand_blank_nodes(o) if o.node? 
    end 
    end 
    g 
end