跨多个解决方案在CONSTRUCT中生成相同的空白节点

时间:2017-09-11 12:37:49

标签: sparql rdf blank-nodes

我曾经遇到过几次我想在CONSTRUCT查询中使用空白节点的情况,但我需要为所有(或几个)查询解决方案获取相同的空白节点。

假设我们在数据集中列出了他们撰写的作者和书籍:

@prefix : <http://example.org#> .

:stephen_king a :Author ;
      :firstName "Stephen" ;
      :authorOf "The Shining", "Cujo".

:stephen_hawking a :Author ;
      :firstName "Stephen" ;
      :authorOf "A Brief History of Time" . 

:virginia_wolf a :Author ;
      :firstName "Virginia" ;
      :authorOf "Mrs Dalloway" . 

例如,假设我想将所有书面作者的名字Stephen绑定到一个空白节点:

PREFIX : <http://example.org#>
CONSTRUCT {
   [ :containsBook ?book ]
}
WHERE {
   ?book ^:authorOf/:firstName "Stephen" .
}

会返回类似的内容:

[ :containsBook "The Shining" ] .
[ :containsBook "A Brief History of Time" ] .
[ :containsBook "Cujo" ] .

但理想的结果是:

[ :containsBook "The Shining" ;
  :containsBook "A Brief History of Time" ;
  :containsBook "Cujo" ] .

关于如何实现这一目标的任何想法?

1 个答案:

答案 0 :(得分:1)

在思考了一段时间后,我想出了一些我认为是一般解决方案的东西。我还没有在许多SPARQL实现上尝试过它,所以如果你发现它不适合你,请提供反馈。基本上,在意识到我们无法对SPARQL如何处理查询结果部分中的数据做任何事情后,我们自然而然地开始考虑将空白节点绑定到变量。所以,让我们说尝试类似的事情:

PREFIX : <http://example.org#>
CONSTRUCT {
   ?bnode :containsBook ?book
}
WHERE {
   ?book :hasAuthor/:firstName "Stephen" .
   BIND(BNODE() AS ?bnode)
}

不,那也行不通。这是为什么?查询评估整个查询,并且对于每个解决方案,将再次调用BIND函数,我们将得到不同的空白节点。

现在这就是诀窍。将查询的BIND部分放在一个组中。这样,由于SPARQL在变量作用域方面的工作方式,我们将在评估查询后最终得到一个连接,其中?bnode部分只被调用一次:

PREFIX : <http://example.org#>
CONSTRUCT {
   ?bnode :containsBook ?book 
}
WHERE {
   ?book :hasAuthor/:firstName "Stephen" .
   { BIND(BNODE() AS ?bnode) }
}

希望有人发现这和我一样有用。欢呼声。