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

时间:2014-03-18 11:36:48

标签: rdf sparql dbpedia virtuoso

通过DBpedia SPARQL endpoint运行此查询可获得许多结果(填充了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))会返回一个空结果集:

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))
} 

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

3 个答案:

答案 0 :(得分:6)

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

在第7张幻灯片的演示文稿An Introduction to SPARQL Optionals by Julian Dolby and Kavitha Srinivas中明确描述了这种情况,其中他们使用了一个示例

optional { ?x name ?label }
optional { ?x nick ?label }

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

  

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

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

其他实施的实验。

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

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

:a :r :x ; :p 2 ; :q 3 .
:b :r :x ; :p 4 ; :q 5 .

然后我们可以使用以下查询并使用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 }
}
----------
| x  | v |
==========
| :b | 4 |
| :a | 2 |
----------

使用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))
}
----------
| x  | v |
==========
| :b | 4 |
| :a | 2 |
----------

联盟或财产的救援路径!

上面提到的幻灯片提到您可以使用union内的optional来获取您正在寻找的结果。根据我提供的数据,这意味着您可以执行此操作:

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

select ?x ?v where { 
  ?x :r :x .
  optional { 
    { ?x :p ?v } union
    { ?x :q ?v }
  }
}
----------
| x  | v |
==========
| :b | 4 |
| :b | 5 |
| :a | 2 |
| :a | 3 |
----------

这没有问题,但使用属性路径可以更简洁。如果您真正想要的是将?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))
}
----------
| x  | v |
==========
| :b | 4 |
| :b | 5 |
| :a | 2 |
| :a | 3 |
----------

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

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

select ?x ?v where { 
  ?x :r :x ; :p|:q ?v 
}
----------
| x  | v |
==========
| :b | 4 |
| :b | 5 |
| :a | 2 |
| :a | 3 |
----------

答案 1 :(得分:0)

罪魁祸首是同一个变量(OPTIONAL)上的双?institution。可能发生的是,一个OPTIONAL总是成功,这意味着另一个总是失败 - 所以?institution变量总是绑定而不是绑定:)

您可以通过以下查询解决此问题:

select ?person ?field ?institution

{
  ?person a dbpedia-owl:Agent .
  OPTIONAL { ?person dbpprop:workInstitution ?inst . }.
  OPTIONAL { ?person dbpprop:workInstitutions ?insts . }.
  BIND (IF(bound(?inst), ?inst, ?insts) AS ?institution )
  ?person dbpprop:field ?field .
  filter(bound(?institution)).
} 

它检查哪个案例成功并将其绑定到结果变量?institution

答案 2 :(得分:-1)

是的,应该修复案件。编译后的SQL包含两个检查,一个用于来自第一个OPTIONAL的机构,另一个用于来自第二个OPTIONAL的机构。正式适当的编译应该是嵌套的子查询,在其输出上有一个过滤器,或者是FITLER(绑定(?institution_1)|| bound(?institution_2))。真正合适的编译器应报告有关奇怪查询的警告,但SPARQL协议不支持警告:|