让我们使用这个数据:
@prefix example: <http://example.org/> .
example:subject1 example:property example:object1 .
example:subject1 example:property example:object2 .
没有属性路径
这样的查询会产生?subjects,其中example:property 有两个不同的值:
prefix example: <http://example.org/>
select ?subject where {
?subject example:property ?object1, ?object2 .
filter ( ?object1 != ?object2 )
}
--------------------
| subject |
====================
| example:subject1 |
| example:subject1 |
--------------------
不过,这几乎是您已经拥有的。要将其归结为一个结果,您可以select distinct:
prefix example: <http://example.org/>
select distinct ?subject where {
?subject example:property ?object1, ?object2 .
filter ( ?object1 != ?object2 )
}
--------------------
| subject |
====================
| example:subject1 |
--------------------
关于属性路径
属性路径是一种表达属性链(前向和后向)的方式,无需沿途绑定所有单独的资源,如果要允许可变数量的边,这一点尤其重要。您可以绑定链两端的东西,但不能绑定中间的东西。
数据在图形上如下所示:
示例:object1 ←example:property 示例:主题 →example:property 示例:object2
如果您想选择与某个主题相关的两个对象,您可以使用属性路径。从example:object1 到example:object2 的路径是(^example:property)/example:property,因为您沿着example:property 边缘向后 到example:subject,然后沿着example:property 边缘向前 em> 到example:object2。如果您想要对象而不是主题,可以使用以下查询:
prefix example: <http://example.org/>
select * where {
?object1 (^example:property)/example:property ?object2 .
filter ( ?object1 != ?object2 )
}
我不认为有一种方便的方法可以使用属性路径获取主题。你可以做类似的事情
?subject property/^property/property/^property ?subject
从?subject 到某个对象,然后回到某个对象(即,不一定是?subject,然后再出去,然后回到?subject,但你不会得到有保证两个不同的对象了。
SPARQL 属性路径的路径语言在 SPARQL 1.1 查询语言推荐(W3C 标准)的9.1 Property Path Syntax 部分进行了描述。值得注意的是,它不包括早期工作草案的Section 3 Path Language 所做的p{n} 表示法。这意味着你的模式
?subject example:property{2} ?object
实际上不是合法的 SPARQL(尽管某些实现可能支持它)。但是,根据工作草案,我们仍然可以确定它的含义。要匹配此模式,您需要格式为
的数据
?subject →example:property [] →example:property ?object
其中[] 只是表示一些任意资源。这与您实际获得的数据不同。因此,即使此语法在 SPARQL 1.1 中是合法的,它也不会为您提供您正在寻找的结果类型。一般来说,属性路径本质上是数据中属性链的一种正则表达式。
结论
虽然属性链可以使某些事情非常变得很好,而使某些原本不可能的事情成为可能(例如,参见 my answer 到 Is it possible to get the position of an element in an RDF Collection in SPARQL?),但我认为它们不适合这个案例。我认为您最好的选择和相当优雅的解决方案是:
?subject example:property ?object1, ?object2 .
filter( ?object1 != ?object2 ).
因为它最清楚地捕获了预期的查询,“找到具有两个不同值 example:property 的 ?subjects。”