我正在尝试使用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的所有功能。
我觉得这是一种常见的查询,应该有更优雅的解决方案(实际上,这是一本食谱解决方案)。我是否正确使用属性路径来解决这个问题,或者我应该采取不同的方法?如果我应该使用属性路径,我是否正确使用它们?
答案 0 :(得分:17)
让我们使用这些数据:
@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←示例:property 示例:subject→示例:property 示例:object2
如果要选择与某个主题相关的两个对象,可以使用属性路径。从example:object1
到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 Property Path Syntax部分中进行了描述。值得注意的是,它不包含p{n}
符号,表示早期工作草案的Section 3 Path Language。这意味着你的模式
?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 ).
因为它最明显地捕获了预期的查询,“找到?subject
的两个不同值的example:property
。”