您无法在 SPARQL 中选择“第 n 个”空白节点,原因有两个:
- RDF 模型是一个集合:三元组是无序的。
- 空白节点表示没有标识符的资源- 这意味着它不能(直接)寻址/识别。
在 RDF/SPARQL 中,您以间接方式使用空白节点:与其尝试直接处理它们(正如我们在上面看到的那样,这是不可能的,因为空白节点的定义是它没有标识符),您查看将它们与其他资源联系起来的事物,即它们所涉及的语句。毕竟,这些语句赋予了空白节点其上下文意义。
在您的情况下:与其他两个空白节点之间的区别在于_:b1
它们扮演主题角色的陈述。因此,要在 SPARQL 中查询_:b1
主题所在的三元组,您应该查看数据并看到它_:b1
唯一具有:p3
value的属性: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 仅用于内部簿记目的 - 您不能使用空白节点进一步查询任何内容。
相信我:这是个坏主意。如果您无法更改数据,请依靠连接空白节点的属性并查询这些数据。