为什么此SPARQL查询未返回任何结果?

4 rdf sparql dbpedia virtuoso

通过DBpedia SPARQL端点运行此查询会获得许多结果(institution填充列):

select ?person ?field ?institution where 

{
  ?person a dbpedia-owl:Agent .
  OPTIONAL { ?person dbpprop:workInstitution ?institution . }
  OPTIONAL { ?person dbpprop:workInstitutions ?institution .}
  ?person dbpprop:field ?field .
} 
Run Code Online (Sandbox Code Playgroud)

但是,添加该行会FILTER(BOUND(?institution))返回一个空结果集:

select ?person ?field ?institution where 

{
  ?person a dbpedia-owl:Agent .
  OPTIONAL { ?person dbpprop:workInstitution ?institution . }
  OPTIONAL { ?person dbpprop:workInstitutions ?institution .}
  ?person dbpprop:field ?field .
  FILTER(BOUND(?institution))
} 
Run Code Online (Sandbox Code Playgroud)

为什么是这样?我希望第一个查询中institution显示结果的所有结果都显示出来,但没有任何结果.

Jos*_*lor 5

快速回答:这是一个DBpedia/Virtuoso错误.

这种情况在Julian Dolby和Kavitha Srinivas在第七张幻灯片中的演示文稿"SPARQL Optionals简介"中有明确描述,其中他们使用了一个示例

optional { ?x name ?label }
optional { ?x nick ?label }
Run Code Online (Sandbox Code Playgroud)

对于具有name值的个人,我们永远不会看到任何nick值,因为optional根据SPARQL规范中的6 Including Optional Values,模式是左关联的.作者在第8栏中总结说:

绑定同一变量的多个OPTIONAL子句很少是你想要的.

你应该得到optional匹配的第一部分的结果.这为变量提供了绑定,所以bound(...)应该是真的.因此,我会说DBpedia行为是一个错误.

其他实现的实验.

这是一个有趣的行为,我们可以用简单的数据重现它.假设我们有这样的数据:

@prefix : <http://stackoverflow.com/q/22478183/1281433/> .

:a :r :x ; :p 2 ; :q 3 .
:b :r :x ; :p 4 ; :q 5 .
Run Code Online (Sandbox Code Playgroud)

然后我们可以使用以下查询并使用Jena获得以下结果.我们只得到属性的结果,:p因为它optional是左关联的,所以:p首先覆盖模式,并且数据中的每个资源都有一个值:p.

prefix : <http://stackoverflow.com/q/22478183/1281433/>

select ?x ?v where { 
  ?x :r :x .
  optional { ?x :p ?v }
  optional { ?x :q ?v }
}
Run Code Online (Sandbox Code Playgroud)
----------
| x  | v |
==========
| :b | 4 |
| :a | 2 |
----------
Run Code Online (Sandbox Code Playgroud)

使用Jena,添加一个filter不会删除任何结果,我认为这是正确的行为,因为?v 绑定的.

prefix : <http://stackoverflow.com/q/22478183/1281433/>

select ?x ?v where { 
  ?x :r :x .
  optional { ?x :p ?v }
  optional { ?x :q ?v }
  filter(bound(?v))
}
Run Code Online (Sandbox Code Playgroud)
----------
| x  | v |
==========
| :b | 4 |
| :a | 2 |
----------
Run Code Online (Sandbox Code Playgroud)

联盟或物业的救援路径!

上面提到的幻灯片提到您可以union在内部使用optional以获得您正在寻找的结果.根据我提供的数据,这意味着您可以这样做:

prefix : <http://stackoverflow.com/q/22478183/1281433/>

select ?x ?v where { 
  ?x :r :x .
  optional { 
    { ?x :p ?v } union
    { ?x :q ?v }
  }
}
Run Code Online (Sandbox Code Playgroud)
----------
| x  | v |
==========
| :b | 4 |
| :b | 5 |
| :a | 2 |
| :a | 3 |
----------
Run Code Online (Sandbox Code Playgroud)

这没有问题,但可以使用属性路径更简洁.如果你真正想要的是绑定?v到的价值无论是:p:q属性,你可以使用一个交替属性路径:

prefix : <http://stackoverflow.com/q/22478183/1281433/>

select ?x ?v where { 
  ?x :r :x .
  optional { ?x :p|:q ?v }
  filter(bound(?v))
}
Run Code Online (Sandbox Code Playgroud)
----------
| x  | v |
==========
| :b | 4 |
| :b | 5 |
| :a | 2 |
| :a | 3 |
----------
Run Code Online (Sandbox Code Playgroud)

当然,如果你正在做filter(bound(?v)),那么模式?x :p|:q ?v真的不再是可选的,所以你应该把它移到查询的主要部分:

prefix : <http://stackoverflow.com/q/22478183/1281433/>

select ?x ?v where { 
  ?x :r :x ; :p|:q ?v 
}
Run Code Online (Sandbox Code Playgroud)
----------
| x  | v |
==========
| :b | 4 |
| :b | 5 |
| :a | 2 |
| :a | 3 |
----------
Run Code Online (Sandbox Code Playgroud)