如何在SPARQL构造查询中递归扩展空白节点?

时间:2012-03-20 01:48:03

标签: sparql rdf semantic-web semantics blank-nodes

这可能很容易回答,但我甚至无法弄清楚如何制定Google查询来找到它。

我正在针对包含空白节点的数据集编写SPARQL构造查询。所以,如果我进行像

这样的查询

CONSTRUCT {?x ?y ?z .} WHERE {?x ?y ?z .}

然后我的一个结果可能是:

nm:John nm:owns _:Node

如果全部

,这是一个问题

_:Node nm:has nm:Hats

三元组也不会以某种方式进入查询结果(因为我使用的一些解析器就像rdflib for Python真的不喜欢悬空的bnodes)。

有没有办法编写我的原始CONSTRUCT查询,以递归方式添加附加到任何bnode结果的所有三元组,以便在我的新图形中没有留下bnodes?

3 个答案:

答案 0 :(得分:11)

递归是不可能的。我能想到的最接近的是SPARQL 1.1 property paths(注意:那个版本已经过时了)但是bnode测试不可用(afaik)。

您可以删除带有尾随bnodes的语句:

CONSTRUCT {?x ?y ?z .} WHERE 
{
  ?x ?y ?z .
  FILTER (!isBlank(?z))
}

或者试着抓住下一位:

CONSTRUCT {?x ?y ?z . ?z ?w ?v } WHERE 
{
  ?x ?y ?z .
  OPTIONAL {
    ?z ?w ?v
    FILTER (isBlank(?z) && !isBlank(?v))
  }
}

(最后一个查询非常严厉,顺便说一句)

使用DESCRIBE可能会更好,这通常会跳过bnodes。

答案 1 :(得分:3)

正如user205512建议的那样,递归执行抓取是不可能的,并且正如他们所指出的那样,使用可选项将任意级别下移到您的数据中,获取节点对于除了非平凡大小的数据库之外的任何事情都是不可行的。 / p>

Bnodes本身是本地作用域,结果集或文件。无法保证您从解析或结果集获得的BNode与数据库中使用的ID相同(尽管某些数据库确保对查询结果保证这一点)。此外,像“select?s {{s?p _:bnodeid1}”这样的查询与“select?where {?s?p?o}”相同 - 请注意,在这种情况下,bnode被视为变量,而不是“具有id'bnodeid1'的东西”这个设计的怪癖使得查询bnodes很困难,所以如果你控制数据,我建议你不要使用它们。为那些本来就是bnodes的东西生成名称并不难,命名资源v.bnodes在查询期间不会增加开销。

这不会帮助你递归和抓取数据,但为此,我不建议做这样的一般查询;它们不能很好地扩展,通常返回的比你想要的还要多。我建议你做更多的定向查询。您的原始构造查询将下拉整个数据库的内容,这通常不是您想要的。

最后,虽然描述可能有用,但没有标准的实现; SPARQL规范没有定义任何特定的行为,因此返回的内容留给数据库供应商,它可以是不同的。如果您计划在应用程序中尝试不同的数据库,那么这会使您的代码不那么便携。如果你想要描述一个特定的行为,你最好自己实现它。对资源进行简洁有界描述之类的操作是一段简单的代码,尽管你可能会遇到一些关于Bnodes的问题。

答案 2 :(得分:1)

关于使用ruby RDF.rb库,它允许在RDF :: Graph对象上使用重要的便捷方法进行SPARQL查询,以下内容应该扩展空白节点。

rdf_type = RDF::SCHEMA.Person # for example
rdf.query([nil, RDF.type, rdf_type]).each_subject do |subject|
  g = RDF::Graph.new
  rdf.query([subject, nil, nil]) do |s,p,o|
    g << [s,p,o]
    g << rdf_expand_blank_nodes(o) if o.node?
  end
end

def rdf_expand_blank_nodes(object)
  g = RDF::Graph.new
  if object.node?
    rdf.query([object, nil, nil]) do |s,p,o|
      g << [s,p,o]
      g << rdf_expand_blank_nodes(o) if o.node?
    end
  end
  g
end