您是对的,您不能在属性路径表达式中使用变量。不过,您可以做几件事,可能会对您有所帮助。
用于检查是否路径存在的通配符
您可以通过将通配符和它的取反来使用通配符,因此您可以执行一个简单的查询来检查是否存在连接两个资源的路径:
<source> (<>|!<>)* <target>
如果您定义了 : 前缀,则可以更短,因为 : 是有效的 IRI:
<source> (:|!:)* <target>
如果两个节点之间有一条路径(或多条路径),您可以使用由?p 连接的通配符路径将其拆分,从而找到路径上的所有?ps:
<source> (:|!:)* ?x .
?x ?p ?y .
?y (:|!:)* <target> .
我认为,您可以通过使用空白节点而不是 ?x 和 ?y 来缩短它:
<source> (:|!:)* [ ?p [ (:|!:)* <target> ] ]
(不过,可能不起作用。我似乎记得语法实际上不允许空白节点内某些地方的属性路径。我不确定。)
对于单个路径,获取属性和位置,然后group_concat
现在,如果两个资源之间只有一条路径,您甚至可以沿该路径获取属性及其位置。您可以按这些位置排序,然后使用 group by 将属性按顺序连接成单个字符串。这可能是最容易看到的一个例子。假设您有以下数据,其中包含从 :a 到 :d 的单一路径:
@prefix : <urn:ex:> .
:a :p1 :b .
:b :p2 :c .
:c :p3 :d .
然后您可以使用这样的查询来获取路径中的每个属性及其位置。 (不过,这仅在只有一条路径时才有效。请参阅我对Is it possible to get the position of an element in an RDF Collection in SPARQL? 的回答,了解更多关于其工作原理的信息。)
prefix : <urn:ex:>
select ?p (count(?mid) as ?pos) where {
:a (:|!:)* ?mid .
?mid (:|!:)* ?x .
?x ?p ?y.
?y (:|!:)* :d
}
group by ?x ?p ?y
-------------
| p | pos |
=============
| :p2 | 2 |
| :p1 | 1 |
| :p3 | 3 |
-------------
现在,如果您按 ?pos 对这些结果进行排序并将 that 查询包装在另一个查询中,那么您可以在 ?p 上使用 group_concat 按顺序获取单个属性字符串。 (不能保证保留的顺序,但这是很常见的行为。有关此技术如何工作的另一个示例,请参阅我对 obtain the matrix in protege 的回答,以及有关为什么不能保证的讨论,请参阅 my answer to Ordering in GROUP_CONCAT in SPARQL 1.1。)
prefix : <urn:ex:>
select (group_concat(concat('<',str(?p),'>');separator=' ') as ?path) {
select ?p (count(?mid) as ?pos) where {
:a (:|!:)* ?mid .
?mid (:|!:)* ?x .
?x ?p ?y.
?y (:|!:)* :d
}
group by ?x ?p ?y
order by ?pos
}
-----------------------------------------
| path |
=========================================
| "<urn:ex:p1> <urn:ex:p2> <urn:ex:p3>" |
-----------------------------------------