SPARQL:选择第n个空白节点

时间:2015-09-29 23:31:43

标签: sparql blank-nodes

采用以下图表:

:Foo :p _:b0 ;
   :p _:b1 ;
   :p _:b2 .

_:b0 :p1 :apple ;
   :p2 :banana .

_:b1 :p3 :cantaloupe ;
   :p4 :date ;
   :p5 :elderberry .

_:b2 :p6 :fig .

注意: :Foo是具有相同谓词:p的三个三元组的主题。每个三元组都有一个空白节点作为其对象。

是否可以编写一个SPARQL查询来选择仅_:b1为主题的所有三元组?

编辑:在提出答案之前,请理解我正在寻找一个聪明的解决方案来解决我在SPARQL中的问题。假设三重存储是固定的(即:无法完成任何更改数据)。我在上面展示的图表是人为的;每个空白节点没有相同数量的p / o三元组。如果他们每个都有一个三元组,那么以下SPARQL查询可能就足够了:

select ?b1 where {
   :Foo :p ?bn .
   ?bn ?p ?o
} limit 1 offset 1

显然,这里的关注点是每次返回相同的空白节点。我知道它是一套固有的无序的,因此无法保证可重复的结果排序;但老实说......对于固定的三重存储,我真诚地怀疑DFA会在查询之间返回不同的空白节点顺序。任何聪明的想法?

1 个答案:

答案 0 :(得分:5)

您无法选择第' SPARQL中的空白节点有两个原因:

  1. RDF模型是:三元组是无序的。
  2. 空白节点表示没有标识符的资源 - 这意味着它无法(直接)寻址/识别。
  3. 在RDF / SPARQL中,您以间接方式处理空白节点:而不是尝试直接解决它们(正如我们上面所看到的那样,因为空白节点的定义是没有标识符),所以查看将它们连接到其他资源的事物,即它们所涉及的语句。毕竟,这些语句赋予空白节点其上下文含义。

    在您的情况下:_:b1和其他两个空白节点之间的差异在他们扮演主题角色的陈述中。因此,要在SPARQL中查询以_:b1为主题的三元组,您应该查看数据并看到_:b1唯一具有值为:p3的属性:cantaloupe。所以你可以像这样查询:

       CONSTRUCT { ?s ?p ?o }
       WHERE { :Foo :p ?s .
               ?s :p3 :cantaloupe ;
                  ?p ?o .
       }
    

    旁注:几个SPARQL引擎实现提供了一些功能来解决没有(全局)标识符的空白节点的问题。在许多情况下,它们引入了一些非标准语法扩展或自定义函数,允许您直接寻址SPARQL查询中的空白节点。我想强调的是,非标准,不太可能在不同的端点上工作,因此最好避免使用。

    如果您发现在没有直接寻址空白节点的情况下确实无法工作,您应该考虑在数据中根本不使用空白节点,而是为这些事物创建适当的IRI。

    更新您对问题的更新基本上是这样的:"我可以在未命名的SPARQL特定实现中使用一些未记录的功能来执行严格来说的查询,不合法,或不保证给出我想要的结果,并侥幸逃脱它?"这个问题的答案是:可能是的,但这取决于您使用的SPARQL实施方式,以及非常糟糕的想法,原因是我所有的原因给你以上。

    许多(大多数?)三重存储确实会在实践中以相同的顺序返回相同的结果,但不能保证(我不能强调这一点)而你真的不应该依赖它。当然,您可以通过在查询中使用ORDER BY子句来获取有序查询结果,但在这种情况下这不会有帮助,因为在SPARQL中未定义空白节点的相对排序(因此查询引擎)可以按其认为合适的任何顺序自由返回_:b1_:b2,即使存在ORDER BY子句也是如此。更糟糕的是:虽然您的输入RDF文件可能包含空节点标识符_:b1_:b2,但这不一定是SPARQL查询将返回的内容。许多三元组用内部生成的id替换空白节点标识符,并且您的SPARQL查询很可能返回_:genid-908c909aeacc4b6da3d3059e18706d68-b1而不是简单_:b1

    即使你能以某种方式可靠地获得空白节点ID:你要用它做什么?空白节点为空。它携带的ID仅用于内部簿记目的 - 您无法使用空白节点进一步查询。

    相信我:这是一个坏主意。如果您无法更改数据,请依赖连接空白节点的属性并查询这些属性。