为什么此SPARQL查询未返回任何结果?(Why is this SPARQL query not returning any results?)

编程入门 行业动态 更新时间:2024-10-11 23:16:22
为什么此SPARQL查询未返回任何结果?(Why is this SPARQL query not returning any results?)

通过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 . }

但是,添加行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结果的查询的所有结果都显示出来,但没有任何结果。

Runninng this query through the DBpedia SPARQL endpoint gets me many results (with the institution column populated):

select ?person ?field ?institution where { ?person a dbpedia-owl:Agent . OPTIONAL { ?person dbpprop:workInstitution ?institution . } OPTIONAL { ?person dbpprop:workInstitutions ?institution .} ?person dbpprop:field ?field . }

However, adding the line FILTER(BOUND(?institution)) returns an empty result set:

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

Why is this? I'd expect all of the results from the first query that have an institution result to show up, but nothing does instead.

最满意答案

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

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

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

对于具有name值的个人,我们永远不会看到任何nick值,因为optional模式是左关联的,根据SPARQL规范中的6 Including Optional Values 。 作者在第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 | ----------

联盟或物业的救援路径!

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

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

Quick answer: this is a DBpedia/Virtuoso bug.

This situation is explicitly described in a presentation An Introduction to SPARQL Optionals by Julian Dolby and Kavitha Srinivas on slide seven, in which they use an example with

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

For individuals who have a name value, we'll never see any of the nick values because the optional patterns are left associative, according to 6 Including Optional Values from the SPARQL specification. The authors conclude on slide eight that:

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

You should get the results for the first optional part that matched. That provides a binding for the variable, so bound(...) should be true. As such, I'd say that the DBpedia behavior is a bug.

Experiments with other implementations.

This is an interesting behavior, and we can reproduce it with simple data. Suppose we have some data like this:

@prefix : <http://stackoverflow.com/q/22478183/1281433/> . :a :r :x ; :p 2 ; :q 3 . :b :r :x ; :p 4 ; :q 5 .

Then we can use the following query and get the following results with Jena. We only get results for the property :p because optional is left associative, so the pattern on :p is covered first, and each resource in our data had a value for :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 | ----------

With Jena, adding a filter doesn't remove any results, which I think is the correct behavior, because ?v is bound.

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 or Property paths to the rescue!

The slides cited above mention that you can use union inside of the optional to get the results you're looking for. With the data I've provided, this means that you can do this:

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

That works without a problem, but it can be made much more concise using property paths. If what you really want is to bind ?v to the value of either the :p or :q property, you can use an alternation property path:

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

Of course, if you're doing filter(bound(?v)), then the pattern ?x :p|:q ?v really isn't optional anymore, so you should probably just move it into the main part of the query:

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

更多推荐

本文发布于:2023-08-01 05:03:00,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1354201.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:query   SPARQL   results   returning

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!