我的一位同事需要获取两组涉及术语关联的 RDF 三元组。这些术语来自一个列表,关联来自一组使用这些术语的三元组。
第一组是所有三元组,术语列表中的任何项目都是三元组的主语或宾语。
第二组是所有三元组,其中任意两个项是一个或两个彼此远离的谓词,其中谓词不一定是双向的。因此,对于术语列表中的 s1 和 s2,两个三元组 s1 → s3 和 s2 → s3 将是有效的。
我想我已经有了答案,但我想请求为 SPARQL 基础做出贡献,并检查自己。
最佳答案
给定这样的数据:
@prefix : <urn:ex:> .
:a :p :b .
:a :p :e .
:b :p :c .
:b :p :d .
:c :p :a .
:c :p :f .
:d :p :a .
:d :p :d .
如果我们取(:b :c)
作为一组有趣的术语,以下查询将找到您感兴趣的所有三元组。请注意,第一组的条件,即。来自 ?s ?p ?o
要么 ?s
或?o
位于术语列表中,也获取第二组的一些内容,即两个术语连接的部分,即,其中 both ?s
和?o
位于术语列表中。
prefix : <urn:ex:>
select distinct ?s ?p ?between ?q ?o where {
# term list appearing twice in order to
# get all pairs of items
values ?x { :b :c }
values ?y { :b :c }
# This handles the first set (where either the subject or
# object is from the term list). Note that the first set
# includes part of the second set; when two terms from
# the list are separated by just one predicate, then it's
# a case where either the subject or object are from the
# term list (since *both* are).
{ ?s ?p ?x bind(?x as ?o)} UNION { ?x ?p ?o bind(?x as ?s)}
UNION
# The rest of the second set is when two terms from the
# list are connected by a path of length two. This is
# a staightforward pattern to write.
{ ?x ?p ?between . ?between ?q ?y .
bind(?x as ?s)
bind(?y as ?o) }
}
在结果中,单个三元组是仅包含 s
的行。 , p
,和o
绑定(bind)。这些涵盖您的第一组,以及第二组的“距离 = 1”部分。第二组的其余部分也绑定(bind) between
和q
。就您问题中的示例而言,between
是 s3
.
$ arq --data data.n3 --query query.sparql
-------------------------------
| s | p | between | q | o |
===============================
| :a | :p | | | :b |
| :b | :p | | | :d |
| :b | :p | | | :c |
| :c | :p | | | :f |
| :c | :p | | | :a |
| :c | :p | :a | :p | :b |
-------------------------------
根据评论更新
鉴于评论中的示例,我认为该查询可以大大缩短为以下内容:
prefix : <urn:ex:>
select distinct ?x ?p ?between ?q ?y where {
values ?x { :b :c }
values ?y { :b :c }
{ ?x ?p ?between } UNION { ?between ?p ?x }
{ ?between ?q ?y } UNION { ?y ?q ?between }
}
一旦我们绑定(bind)?x ?p ?between
或?between ?p ?x
,我们只是说 ?x
之间有一个边缘(在任一方向)和?between
。 ?y
和?q
扩展该路径,这样我们就有:
?x --?p-- ?between --?q-- ?y
其中 --?p--
的实际方向和--?q--
可以向左或向右。这涵盖了我们需要的所有情况。可能不难理解为什么长度为 2 的路径会匹配此模式,但三元组的情况(其中主语或宾语只是一个特殊术语)值得详细说明。给定一个三元组
<term> <prop> <non-term>
我们可以得到路径
<term> --<prop>-- <non-term> --<prop>-- <term>
这适用于 <term>
的情况是对象并且 <non-term>
是主题。它还涵盖了主语和宾语都是术语的情况。根据以上数据,结果为:
$ arq --data data.n3 --query paths.sparql
-------------------------------
| x | p | between | q | y |
===============================
| :b | :p | :d | :p | :b |
| :b | :p | :c | :p | :b |
| :b | :p | :a | :p | :b |
| :c | :p | :a | :p | :b |
| :b | :p | :a | :p | :c |
| :c | :p | :f | :p | :c |
| :c | :p | :a | :p | :c |
| :c | :p | :b | :p | :c |
-------------------------------
如果我们添加一些有关哪种方式的信息 ?p
和?q
我们指出,我们可以重建路径:
prefix : <urn:ex:>
select distinct ?x ?p ?pdir ?between ?q ?qdir ?y where {
values ?x { :b :c }
values ?y { :b :c }
{ ?x ?p ?between bind("right" as ?pdir)} UNION { ?between ?p ?x bind("left" as ?pdir)}
{ ?between ?q ?y bind("right" as ?qdir)} UNION { ?y ?q ?between bind("left" as ?qdir)}
}
这给出了输出:
$ arq --data data.n3 --query paths.sparql
---------------------------------------------------
| x | p | pdir | between | q | qdir | y |
===================================================
| :b | :p | "right" | :d | :p | "left" | :b | # :b -> :d
| :b | :p | "right" | :c | :p | "left" | :b | # :b -> :c
| :b | :p | "left" | :a | :p | "right" | :b | # :a -> :b
| :c | :p | "right" | :a | :p | "right" | :b | # :c -> :a -> :b
| :b | :p | "left" | :a | :p | "left" | :c | # :c -> :a -> :b
| :c | :p | "right" | :f | :p | "left" | :c | # :c -> :f
| :c | :p | "right" | :a | :p | "left" | :c | # :c -> :a
| :c | :p | "left" | :b | :p | "right" | :c | # :b -> :c
---------------------------------------------------
c -> a -> b
重复出现路径,但可能会被过滤掉。
如果您实际上是在此处查找三元组集合,而不是特定路径,则可以使用构造查询来返回图形(因为三元组集合是图形):
prefix : <urn:ex:>
construct {
?s1 ?p ?o1 .
?s2 ?q ?o2 .
}
where {
values ?x { :b :c }
values ?y { :b :c }
{ ?x ?p ?between .
bind(?x as ?s1)
bind(?between as ?o1) }
UNION
{ ?between ?p ?x .
bind(?between as ?s1)
bind(?x as ?o1)}
{ ?between ?q ?y .
bind(?between as ?s2)
bind(?y as ?o2) }
UNION
{ ?y ?q ?between .
bind(?y as ?s2)
bind(?between as ?o2)}
}
$ arq --data data.n3 --query paths-construct.sparql
@prefix : <urn:ex:> .
<urn:ex:b>
<urn:ex:p> <urn:ex:c> ;
<urn:ex:p> <urn:ex:d> .
<urn:ex:c>
<urn:ex:p> <urn:ex:f> ;
<urn:ex:p> <urn:ex:a> .
<urn:ex:a>
<urn:ex:p> <urn:ex:b> .
关于rdf - 如何从 SPARQL 中的术语列表中获取基本术语关联,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17880965/