rdf - 如何从 SPARQL 中的术语列表中获取基本术语关联

标签 rdf sparql triples

我的一位同事需要获取两组涉及术语关联的 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) betweenq 。就您问题中的示例而言,betweens3 .

$ 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/

相关文章:

java - SPARQL 类型转换?

rdf - 使用定义的 OWL 本体创建 RDF

rdf - SPARQL 查询构造带有选择路径的子图(路径有不同的长度)

python - SPARQLWrapper 不返回 JSON

rdf - RDF中具体化的解释

java - Sesame NativeRDF 写入/tmp

java - 从 EC2 窗口访问 Amazon Neptune

recursion - 是否可以在 SPARQL 中表达递归定义?

Sparql-实体和实例的数量?

stream - C-SPARQL 查询 - 精确匹配字符串文字