如何从 RDF Graph 中的给定资源构造获取整个子图?

How do I construct get the whole sub graph from a given resource in RDF Graph?

如果这是 RDF 图,给定资源 A,我需要构建连接到 A 的所有三元组直到结束。在这里我必须得到图表包括 B、C、D、E

在那之后,假设我得到了这张图,只想从起点 (:A) 开始,沿着以 属性 上的边结束的路径生成子图:d .例如,如果 A1 作为起点,d 作为 属性,我们将构建:

:A1 :a :B1, 
:B1 :b :S1,
:B1 :b :S2,
:S1 :d :D1,
:S2 :d :D2,

RDF 图最重要的部分是属性。由于您的图表未定义属性,因此问题相当含糊,但归结为几个场景。

如果图中的属性相同,则可以使用可传递的属性路径:

CONSTRUCT {:A :prop ?rsc }
WHERE {
   :A :prop* ?rsc .
}

如果图中有多种类型的pf属性,获取传递闭包会比较复杂。例如,以下将获取示例图中的所有属性:

CONSTRUCT {
   :A ?p ?rsc1 .
   :A ?p1 ?rsc2 .
}
WHERE {
   :A ?p ?rsc1 .
   OPTIONAL {?rsc1 ?p1 ?rsc2 .}
}

请注意,这有两个层次。对于任意级别,最好调用以下查询,直到没有创建新的三元组:

CONSTRUCT {
   ?rsc ?p ?o .
}
WHERE {
   ?rsc ?p ?o .
}

...其中 rsc 最初绑定到 :A,随后的迭代绑定到 ?o 的值。

不可能用一个 CONSTRUCT 查询得到整个连通图。您需要 运行 多个查询。即使有多个查询,当涉及空白节点时也会变得有点棘手,因为您将不得不逐渐扩展它们的上下文,并且 return 在每个后续查询中都使用此上下文。

有关执行此操作的代码示例,请参阅:https://github.com/apache/clerezza-rdf-core/tree/master/impl.sparql/src/main/java/org/apache/clerezza/commons/rdf/impl/sparql

第一种情况

要获取整个连通图,需要使用通配符属性路径跟随大部分路径,然后用实际变量抓取最后的link。我通常在构造通配符时使用空的相对路径,以便使用 <>|!<> 作为通配符,但既然你提到你的端点不喜欢它,你也可以使用你喜欢的任何绝对 IRI。例如,

prefix x: <urn:ex:>

construct { ?s ?p ?o }
where { :A (x:|!x:)* ?s . ?s ?p ?o . }

这是有效的,因为每个 属性 要么是 x: 要么不是,所以 x:|!x: 匹配每个属性,然后 (x:|!x:)* 是任意长度的路径,包括长度为零的路径,也就是说 ?s 将绑定到从 :a 可到达的所有内容,包括 :a 本身。然后你抓住了 ?s 是主题的三元组。当您构造所有这些三元组的图时,您会得到您正在寻找的子图。

这是一个基于您显示的图表的示例。我对不同的边使用了不同的属性来证明它有效,但如果它们都相同,这也将有效。

@prefix : <urn:ex:> .

:A :p :B, :C .
:B :q :D .
:C :r :E .

:F :s :G .
:G :t :H .
prefix x: <urn:ex:>
prefix : <urn:ex:>

construct {
  ?s ?p ?o
}
where {
  :A (x:|!x:)* ?s .
  ?s ?p ?o .
}

由于这是一个 construct 查询,结果是一个图表,而不是 "table"。它包含我们期望的三元组:

@prefix :      <urn:ex:> .

:C      :r      :E .

:B      :q      :D .

:A      :p      :B , :C .

第二种情况

如果你想确保路径以特定类型的边结束,你也可以这样做。如果你只想要从 A1 到那些以 d 上的边结尾的路径,你可以这样做:

prefix x: <urn:ex:>      #-- arbitrary, used for the property path.
prefix : <...>           #-- whatever you need for your data.

construct {
  ?s1 ?p ?o1 .           #-- internal edge in the path
  ?s2 :d ?o2 .           #-- final edge in the path
}
where {
  :A (x:|!x:)* ?s1 .     #-- start at :A and go any length into the path
  ?s1 ?p ?o1 .           #-- get the triple from within the path, but make
  ?o1 (x:|!x:)* ?s2 .    #-- sure that from ?o1 you can get to to some other
  ?s2 :d ?o2 .           #-- ?s2 that's related to an ?o2 by property :d .
}