rdf - 为什么这个 SPARQL 查询没有返回任何结果?

标签 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结果显示出来,但什么都没有。

最佳答案

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

演示文稿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 中得出结论:

Multiple OPTIONAL clauses binding the same variable is rarely what you want.



您应该得到第一个 optional 的结果匹配的部分。这为变量提供了一个绑定(bind),所以 bound(...)应该是真的。因此,我会说 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是绑定(bind)的。
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 |
----------

工会或属性(property)的救援路径!

上面引用的幻灯片提到您可以使用 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 |
----------

这没有问题,但是使用属性路径可以使其更加简洁。如果你真正想要的是绑定(bind)?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 |
----------

关于rdf - 为什么这个 SPARQL 查询没有返回任何结果?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22478183/

相关文章:

tree - 用于折叠树分支的 SPARQL 查询(汇总拓扑)

rdf - 如何知道 DBpedia 中某个实体的确切名称/URI?

rdf - SPARQL 查询提取人员的主语、谓语和宾语

rdf - 使用Pellet作为推理机的OutOfMemoryError

rdf - OWL 我怎么知道某个东西应该是类还是实例?

java - 耶拿从海龟中读取失败

python - 如何搜索 freebase 数据转储

sparql - DBpedia 和 SPARQL : Query with accent marks does not work

graph - 使用 SPARQL 查询查找最短路径

sparql - 根据 URI 前缀从 DBpedia SPARQL 查询中排除结果