4

我正在尝试使用 SPARQL 返回三元组,其中同一主题具有相同属性的多个对象,如下所示:

example:subject1 example:property example:object1
example:subject1 example:property example:object2

我觉得这样的查询应该使用属性路径:

SELECT ?subject WHERE {
  ?subject example:property{2} ?object .
}

我正在使用 Jena 2.6.4 运行此属性路径查询,但没有得到任何结果。这是因为耶拿吗?还是我对查询的措辞不正确?以下查询返回我期望的结果,但不优雅:

SELECT ?subject WHERE {
  ?subject example:property ?object1 .
  ?subject example:property ?object2 .
  FILTER(!(?object1=?object2))
}

如果我使用 ; ,属性路径查询将example:property{1,2}返回example:property{1}结果 只是不是我想要的结果。所以,我知道 Jena 正确解释了语法,但我也知道这是 Jena 的旧版本,因此它可能无法识别 SPARQL 1.1 的所有功能。

我觉得这是一种常见的查询,应该有一个更优雅的解决方案(实际上,一个食谱解决方案)。我使用属性路径来解决这个问题是正确的,还是应该采取不同的方法?如果我应该使用属性路径,我是否正确使用它们?

4

1 回答 1

20

让我们使用这些数据:

@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 |
--------------------

关于属性路径

属性路径是一种表达属性链(向前和向后)的方式,无需沿途绑定所有单独的资源,如果要允许可变数量的边,这一点尤其重要。您可以绑定链两端的东西,但不能绑定中间的东西。

数据以图形方式显示如下:

        示例:对象 1 ←示例:属性示例:主题 →示例:属性示例:对象2

如果要选择与某个主题相关的两个对象,可以使用属性路径。example:object1从to的路径example:object2(^example:property)/example:property,因为您沿着一条example:property向后到达example:subject,然后沿着一条example:property向前到达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 部分属性路径语法中进行了描述。值得注意的是,它包括早期工作草案的第 3 节路径语言p{n}所做的符号。这意味着你的模式

?subject example:property{2} ?object

实际上不是合法的 SPARQL(尽管某些实现可能支持它)。但是,根据工作草案,我们仍然可以确定它的含义。要匹配此模式,您需要表单的数据

        ?subject → example:property [] → example:property ?object

其中[]只是表示一些任意资源。这与您实际获得的数据不同。因此,即使此语法在 SPARQL 1.1 中是合法的,它也不会为您提供您正在寻找的结果类型。一般来说,属性路径本质上是数据中属性链的一种正则表达式。

结论

虽然属性链可以使某些事情变得非常好,而使某些原本不可能的事情成为可能(例如,请参阅Is it possible to get the position of an element in an RDF Collection in SPARQL? 的回答),但我不认为他们重新适合这种情况。我认为您最好的选择和相当优雅的解决方案是:

?subject example:property ?object1, ?object2 .
filter( ?object1 != ?object2 ).

因为它最清楚地捕获了预期的查询,“找到?subject具有两个不同值的 s example:property。”</p>

于 2013-09-20T15:12:48.977 回答