2013-04-25 77 views
7

大家好rdf/sparql開發人員。這裏有一個問題讓我嘮叨了一會兒,但是自rdf和sparql規範發佈以來,似乎沒有人能夠準確回答它。通過集合和rdf:容器進行Sparql查詢?

爲了說明這種情況,RDF定義了幾種方法來處理資源的多值屬性;從創建具有相同子噴射謂詞uris的三元組到集合或容器。這是很好的,因爲每種模式都有自己的特點。

但是從SPARQL的觀點來看,在我看來,查詢這些結構會導致過於複雜的查詢(更糟糕的是)無法轉錄爲明智的結果集:您無法使用變量來查詢任意列表,長度和propertyPath不保留「自然」順序。

以一種天真的方式,在很多SELECT或ASK查詢中,如果我想查詢或過濾容器或列表的值,我不會在乎大部分時間都在意底層模式是真的(如果有的話) )。因此,例如:

<rdf:Description rdf:about="urn:1"> 
    <rdfs:label> 
     <rdf:Alt> 
      <rdf:li xml:lang="fr">Exemple n°1</rdf:li> 
      <rdf:li xml:lang="en">Example #1</rdf:li> 
     </rdf:Alt> 
    </rdfs:label> 
    <my:release> 
     <rdf:Seq> 
      <rdf:li>10.0</rdf:li> 
      <rdf:li>2.4</rdf:li> 
      <rdf:li>1.1.2</rdf:li> 
      <rdf:li>0.9</rdf:li> 
     </rdf:Seq> 
    </my:release> 
</rdf:Description> 

<rdf:Description rdf:about="urn:2"> 
    <rdfs:label xml:lang="en">Example #2</rdfs:label> 
</rdf:Description> 

顯然,我希望雙方的資源來回答查詢:

SELECT ?res WHERE { ?res rdfs:label ?label . FILTER (contains(?label, 'Example'@en) } 

我也希望查詢:

SELECT ?ver WHERE { <urn:1> my:release ?ver } 

返回RDF:序列元素(或者任何rdf:Alt就是這個原因)按照原始順序(對於其他模式,保留原始順序還是不保留,爲什麼不保留它)? - 除非通過ORDER BY明確指定條款。

當然,有必要保持與舊方式的兼容性,所以也許有可能使用新的操作符來擴展propertyPath語法?

我覺得這會簡化很多日常的SPARQL用例。

對你有意義嗎? 此外,你看到有什麼理由不嘗試實施這個?

編輯修正的例子的骨灰盒:2周的rdfs:標籤值,這是不正確

+0

請參閱https://bitbucket.org/dotnetrdf/dotnetrdf/wiki/UserGuide/Typed%20Values%20and%20Lists for dotNetRDF的RDF列表的程序化API – RobV 2013-04-26 17:11:06

+0

感謝您的提示Rob,但我主要是在sparql級別認爲只要能夠簡單地查詢或過濾SPARQL屬性而無需後處理,事先知道該對象是否爲容器,並且不採用如下醜陋的sparql:SELECT coalesce(?lit,?labelObj)作爲?label {?s rdfs:label?labelObj。可選{?label rdf:next */rdf:first?lit FILTER(isLiteral(?lit))})}或者這樣的事情...... – Max 2013-04-26 17:28:13

+0

事實上,我在考慮更多的XPath端口上的propertyPaths模式,如rdfs:label [ ],rdfs:label [0]或rdfs:label [i..n],例如它可以派上用場並回答容器/列表或簡單事實模式(當然事實模式沒有可預測性......) ) – Max 2013-04-26 17:40:56

回答

4

RDF定義集合和容器詞彙,但他們沒有任何特殊的含義,如何含有這些圖表應該解釋條款。它們不適用於表示多值屬性,也不適合表示多值屬性。

在一般情況下,他說:

:A :predicate [ a rdf:Alt ; rdf:_1 :B ; rdf:_2 :C ] . 

不等同於

:A :predicate :B , :C . 

假設謂詞是貓頭鷹:sameAs的:

:A owl:sameAs [ a rdf:Alt ; rdf:_1 :B ; rdf:_2 :C ] . 

上面說:一個名字個人含有:B和:C,而:

:A owl:sameAs :B , :C . 

說:A,:B,和:C是相同個體。

對於容器和集合(除了rdf:List的語法簡寫),SPARQL是不可知的。如果您想要更方便地使用集合,則許多RDF API(包括Jenardflib)都具有一流的表示形式。

補遺

建模多值屬性的方式 - 即,模型,這兩個「實施例N°1」 @fr和和「實施例#1」 @en是甕標籤: 1 - 是簡單地陳述了兩個事實:

<rdf:Description rdf:about="urn:1"> 
    <rdfs:label xml:lang="fr">Exemple n°1</rdfs:label> 
    <rdfs:label xml:lang="en">Example #1</rdfs:label> 
    ... 
</rdf:Description> 

和查詢:

SELECT ?res WHERE { ?res rdfs:label ?label . FILTER (contains(?label, 'Example'@en)) } 

將匹配英文標籤<甕:1 >和< urn:2 >。

對於我的:釋放屬性,你有一個多值屬性和它的值的順序,這有點棘手。您可以定義一個新屬性(例如my:releases,其值爲rdf:List或rdf:Seq)。 my:release提供了直接的關係,我:發佈了一個指定明確排序的間接關係。推理商店和適當的規則,你只需要提供後者。不幸的是,這並不能讓SPARQL中的順序變得更簡單。

的做法,更容易在SPARQL和非推理商店將是使自己與定義的排序屬性對象的版本一起工作:

<rdf:Description rdf:about="urn:1"> 
    <rdfs:label xml:lang="fr">Exemple n&#xB0;1</rdfs:label> 
    <rdfs:label xml:lang="en">Example #1</rdfs:label> 
    <my:release> 
     <my:Release> 
     <dc:issued rdf:datatype="&xsd;date">2008-10-10/dc:issued> 
     <my:version>10.0</my:version> 
     </my:Release> 
    </my:release> 
    <my:release> 
     <my:Release> 
     <my:version>2.4</my:version> 
     <dc:issued rdf:datatype="&xsd;date">2007-05-01</dc:issued> 
     </my:Release> 
    </my:release> 
    ... 
    </rdf:Description> 

在上面,日期可以用來由於沒有明確的順序,因此排序結果。該查詢只稍微複雜一些:

SELECT ?ver 
WHERE { <urn:1> my:release [ my:version ?ver ; dc:issued ?date ] } 
ORDER BY ?date 
+0

好的,感謝指向我的RDF用例的反例,我並不是說這些模式是相同的,或者應該完全忽略容器,但如果需要,SPARQL應該提供一個「快捷方式」來查詢。那麼您能否指出「最佳」方式來模擬多值排序屬性,以及如何對SPARQL進行查詢? – Max 2013-04-26 06:25:52

+0

(更新;請參閱附錄) – user2313838 2013-04-26 15:26:31

+0

感謝您的更新,它非常清楚。 – Max 2013-04-26 17:08:45

3

我意識到,這個問題已經有了答案,但它是值得考慮看看,如果你使用RDF列表,而不是其他類型的RDF的,你可以在這裏做什麼容器。首先,您所提供的海龜(提供命名空間聲明後)的數據是:

@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> . 
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> . 
@prefix my: <https://stackoverflow.com/q/16223095/1281433/> . 

<urn:2> rdfs:label "Example #2"@en . 

<urn:1> rdfs:label [ a  rdf:Alt ; 
         rdf:_1 "Exemple n°1"@fr ; 
         rdf:_2 "Example #1"@en 
        ] ; 
     my:release [ a  rdf:Seq ; 
         rdf:_1 "10.0" ; 
         rdf:_2 "2.4" ; 
         rdf:_3 "1.1.2" ; 
         rdf:_4 "0.9" 
        ] . 

屬性rdf:_n是這裏的困難,因爲它們提供任何真正要想在元素的唯一的事序列。(而alt並沒有真正有一個重要的序列,但它仍然使用rdf:_n屬性。)如果你使用,使rdf:_n屬性可選一個SPARQL屬性路徑可以得到所有三個標籤:

prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> 
prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> 

select ?x ?label where { 
    ?x rdfs:label/(rdf:_1|rdf:_2|rdf:_3)* ?label 
    filter(isLiteral(?label)) 
} 
------------------------------ 
| x  | label   | 
============================== 
| <urn:1> | "Exemple n°1"@fr | 
| <urn:1> | "Example #1"@en | 
| <urn:2> | "Example #2"@en | 
------------------------------ 

讓我們來看看你可以用RDF列表做些什麼。如果你使用的名單,然後你的數據是這樣的:

@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> . 
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> . 
@prefix my: <https://stackoverflow.com/q/16223095/1281433/> . 

<urn:2> rdfs:label "Example #2"@en . 

<urn:1> rdfs:label ("Exemple n°1"@fr "Example #1"@en) ; 
     my:release ("10.0" "2.4" "1.1.2" "0.9") . 

現在你可以將標籤相對容易:

prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> 
prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> 

select ?x ?label where { 
    ?x rdfs:label/(rdf:rest*/rdf:first)* ?label 
    filter(isLiteral(?label)) 
} 
------------------------------ 
| x  | label   | 
============================== 
| <urn:1> | "Exemple n°1"@fr | 
| <urn:1> | "Example #1"@en | 
| <urn:2> | "Example #2"@en | 
------------------------------ 

如果你想在標籤列表中的位置的標籤,你甚至可以得到,但它使查詢有點複雜:

prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> 
prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> 

select ?x ?label (count(?mid)-1 as ?position) where { 
    ?x rdfs:label ?y . 
    ?y rdf:rest* ?mid . ?mid rdf:rest*/rdf:first? ?label . 
    filter(isLiteral(?label)) 
} 
group by ?x ?label 
----------------------------------------- 
| x  | label   | position | 
========================================= 
| <urn:1> | "Exemple n°1"@fr | 0  | 
| <urn:1> | "Example #1"@en | 1  | 
| <urn:2> | "Example #2"@en | 0  | 
----------------------------------------- 

這使用了技術在Is it possible to get the position of an element in an RDF Collection in SPARQL?來計算即是rdfs:label對象,從0開始,並分配到0不在列表中的元素列表中的每個值的位置。

+1

約書亞,你的回答沒有解決最初的問題,但我必須同意列表要容易得多。我首先考慮了容器,因爲它不那麼「冗長」,然後將真正的「類型」列表綁定在RDF中。簡而言之,即使更新更簡單,它也證明了一種痛苦,即以查詢方式處理容器,並且我認爲這些多值屬性背後的有效邏輯仍然可以在其他地方處理...所以爲了使其更短感謝你的回答 ;) – Max 2014-03-07 13:30:30