如何从 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 .
}
如果这是 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 .
}