[英]Sparql queries over collection and rdf:containers?
嗨所有rdf / sparql开发人员。 这个问题一直困扰着我一段时间,但似乎没有人能够准确地回答它,因为rdf和sparql规范已经发布。
为了说明这种情况,RDF定义了几种处理资源多值属性的方法; 从使用相同的subjet-predicate 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:Seq元素(或任何rdf:Alt)(对于其他模式,如果保留原始顺序无关紧要,为什么不保留它呢?) - 除非明确指定通过ORDER BY子句。
当然,有必要保持与旧方法的兼容性,所以也许有可能使用new运算符扩展propertyPath语法?
我觉得它会简化日常的SPARQL用例。
这对你有意义吗? 此外,你有没有理由不尝试实施这个?
编辑更正了示例的urn:2 rdfs:标签值不正确
我意识到这个问题已经有了答案,但是如果你使用RDF列表而不是其他类型的RDF容器,那么值得看看你能在这里做些什么。 首先,您在Turtle中提供的数据(在提供名称空间声明之后)是:
@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
是这里的难点,因为它们是唯一能够为序列中的元素提供任何实际顺序的东西。 (虽然它仍然使用rdf:_n
属性,但alt实际上没有重要的序列。)如果使用SPARQL属性路径使rdf:_n
属性可选,则可以获取所有三个标签:
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 |
-----------------------------------------
这使用了这种技术是否可以在SPARQL中获取RDF集合中元素的位置? 计算作为rdfs:label
对象的列表中每个值的位置,从0
开始,并将0
分配给不在列表中的元素。
RDF定义了集合和容器的词汇表,但它们在如何解释包含它们的图形方面没有特殊含义。 它们不适用于并且不适合表示多值属性。
一般来说,说:
:A :predicate [ a rdf:Alt ; rdf:_1 :B ; rdf:_2 :C ] .
不等于
:A :predicate :B , :C .
假设谓词是owl:sameAs:
:A owl:sameAs [ a rdf:Alt ; rdf:_1 :B ; rdf:_2 :C ] .
上面说的是:A命名一个包含 :B和C的个体,而:
:A owl:sameAs :B , :C .
说:A,:B和:C是同一个人。
SPARQL与容器和集合无关(除了rdf:List的语法简写)。 如果您想要一种更方便的处理集合的方法,许多RDF API(包括Jena和rdflib)都具有一流的表示形式。
附录
对多值属性进行建模的方法 - 也就是说,对“示例n°1”@fr和“示例#1”进行建模是urn: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) ) }
将匹配<urn:1>和<urn:2>的英文标签。
对于my:release属性,你有一个多值属性和它的值的排序,这有点棘手。 您可以定义一个新属性(例如)my:releases,其值为rdf:List或rdf:Seq。 my:release给出直接关系,my:释放间接关系,指定显式排序。 使用推理存储和适当的规则,您只需提供后者。 不幸的是,这并没有使得在SPARQL中使用排序变得更容易。
在SPARQL和非推理存储中更容易使用的方法是使版本本身成为具有定义排序的属性的对象:
<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>
<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
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.