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

Rdf 如何从SPARQL中的术语列表中获取基本术语关联,rdf,sparql,triples,Rdf,Sparql,Triples,我的一个同事需要得到两组涉及术语关联的RDF三元组。术语来自一个列表,关联来自一组使用这些术语的三元组 第一组是所有三元组,术语列表中的任何项都是三元组的主语或宾语 第二组是所有三元组,任何两个术语都是一个或两个彼此相距较远的谓词,其中谓词不一定是双向的。对于术语表中的s1和s2,两个三元组s1→ s3和s2→ s3将是有效的 我想我已经有了答案,但我想请求为SPARQL库做贡献,并检查自己。给出如下数据: @prefix : <urn:ex:> . :a :p :b . :a

我的一个同事需要得到两组涉及术语关联的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 .
在结果中,单三元组是仅绑定了
s
p
o
的行。这包括你的第一套,以及你的第二套的“距离=1”部分。第二组的其余部分也在和
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 }
}
其中,
--?p--
--?q--
的实际方向可以是左或右。这涵盖了我们需要的所有案例。也许不难看出为什么长度为2的路径会与此模式匹配,但对于三元组,只有主语或宾语是一个特殊术语的情况值得详细阐述。给三个

<term> <prop> <non-term>
如果我们添加一些关于
?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)}
}
有一个重复的
c->a->b
路径,但可能会被过滤掉

如果您在这里实际查找的是三元组,而不是特定路径,则可以使用构造查询返回一个图(因为三元组是一个图):

前缀:
构造{
?s1?p?o1。
?s2?q?o2。
}
何处{
值?x{:b:c}
值?y{:b:c}
{?x?p?介于两者之间。
结合(?x为?s1)
结合(?在as?o1之间)}
联合
{?在?p?x之间。
结合(?在as?s1之间)
结合(?x as?o1)}
{?在?q?y之间。
结合(?as?s2之间)
结合(?y为?o2)}
联合
{?y?q?介于两者之间。
绑定(?y为?s2)
结合(?在as?o2之间)}
}
$arq--data.n3--query path-construct.sparql
@前缀:。
;
.
;
.
.

您可以在查询中使用UNION。在这两种情况下,您都有一组正在寻找的模式,并且希望从这些模式的联合中收集信息

对于第一组,获取包含subject或object中列表项的所有三元组

SELECT ?s ?p ?o # result triples
WHERE
{
  # get a term bound to ?term
  GRAPH <urn:termsList/>
  { ?term a <urn:types/word> } # or however the terms are stored

  # match ?term against the basic patterns
  GRAPH <urn:associations/>
  {
    {
      ?term ?p ?o . # basic pattern #1
      BIND(?term AS ?s) # so that ?term shows up in the results
    }
    UNION # take ?term as either subject or object
    { 
      ?s ?p ?term . # basic pattern #2
      BIND(?term AS ?o)
    } 
  }
}

在每个模式匹配之后,使用绑定将?项放置在结果中的适当位置。例如,第一个模式刚刚绑定了?p和?o,因此接下来需要绑定它们对应的?s,否则它将显示为空白

对于第二组,首先我们从列表中得到两个单词。我们需要多对多匹配:

?term1 a … .
?term2 a … .
基本模式:

?term1 ?p1 ?term2

?term1 ?p1 ?term .
?term2 ?p2 ?term .

?term1 ?p1 ?term .
?term ?p2 ?term2 .

?term ?p1 ?term1 .
?term ?p2 ?term2 .
在最后三个端子上各添加一个过滤器,以确保端子1和端子2不相同:

FILTER(!SAMETERM(?term1, ?term2))
(我们可以将这些过滤器放在所有联合之外,但在进一步使用变量之前,在本地过滤变量更有效。)

最后将结果合并在一起:

SELECT ?s1 ?p1 ?o1 ?s2 ?p2 ?o2
WHERE
{
  GRAPH <urn:termsList/>
  { 
    ?term1 a <urn:types/word> . # outer loop variable
    ?term2 a <urn:types/word> . # inner loop variable
  }
  GRAPH <urn:associations/>
  {
    {
      # Only need to check one direction; either end gets 
      # matched into ?term1 at some point
      ?term1 ?p1 ?term2 .
      BIND (?term1 AS ?s1) .
      BIND (?term2 AS ?o1) . # Note we leave ?s2, ?p2, ?o2 unbound here
    }
    UNION
    { 
      ?term1 ?p1 ?term .
      ?term2 ?p2 ?term .
      FILTER(!SAMETERM(?term1, ?term2))
      BIND(?term1 AS ?s1) .
      BIND(?term AS ?o1) .
      BIND(?term2 AS ?s2) .
      BIND(?term AS ?o2)
    }
    UNION
    { 
      ?term1 ?p1 ?term .
      ?term ?p2 ?term2 .
      FILTER(!SAMETERM(?term1, ?term2))
      BIND(?term1 AS ?s1) .
      BIND(?term AS ?o1) .
      BIND(?term AS ?s2) .
      BIND(?term2 AS ?o2)
    }
    UNION
    { 
      ?term ?p1 ?term1 .
      ?term ?p2 ?term2 .
      FILTER(!SAMETERM(?term1, ?term2))
      BIND(?term AS ?s1) .
      BIND(?term1 AS ?o1) .
      BIND(?term AS ?s2) .
      BIND(?term2 AS ?o2)
    }
  }
}
当然,这使得?s2和?o2的绑定变得不必要,因为它们仅为SELECT绑定


“如果我们在像他那样的死亡中与[基督]结合,我们一定会在像他那样的复活中与他结合”(罗马书6:5 ESV)。

如果你已经找到了一个有效的解决方案,这类问题可能会更多地讨论这个话题。如果这些解决方案中的某个不起作用,那么展示它会很有用。事实上,这个问题是相当开放的,可能属于“过于宽泛”的类别:“可能的答案太多,或者好的答案对于这种格式来说太长。请添加详细信息以缩小答案集,或者隔离一个可以在几段中回答的问题。”谢谢,Joshua。唯一的问题是,我需要第二个集合包含形式a->c,a->b和c->a,b->a的模式。尽管如此,这些都是对你答案的简单补充,我的答案与之类似,因此也实现了佐证的目标2。@NargothBond当你说“谓词不一定是双向的”时,我不太清楚你的意思。给出这个新的例子,你的意思是什么“列表中的两个术语通过长度为2的无向路径连接”(即,当每个三元组被视为主语和谓语之间的无向边时,长度为2的路径)?:P对不起,我似乎很擅长不清楚。我想说的是“好像它们由两条无向边连接,“即使RDF边是根据定义定向的。@NargothBond好的,基于这一澄清,我已经用一个更短的解决方案更新了答案。谢谢!那做得更好。
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> .
SELECT ?s ?p ?o # result triples
WHERE
{
  # get a term bound to ?term
  GRAPH <urn:termsList/>
  { ?term a <urn:types/word> } # or however the terms are stored

  # match ?term against the basic patterns
  GRAPH <urn:associations/>
  {
    {
      ?term ?p ?o . # basic pattern #1
      BIND(?term AS ?s) # so that ?term shows up in the results
    }
    UNION # take ?term as either subject or object
    { 
      ?s ?p ?term . # basic pattern #2
      BIND(?term AS ?o)
    } 
  }
}
?term ?p ?o
?s ?p ?term.
?term1 a … .
?term2 a … .
?term1 ?p1 ?term2

?term1 ?p1 ?term .
?term2 ?p2 ?term .

?term1 ?p1 ?term .
?term ?p2 ?term2 .

?term ?p1 ?term1 .
?term ?p2 ?term2 .
FILTER(!SAMETERM(?term1, ?term2))
SELECT ?s1 ?p1 ?o1 ?s2 ?p2 ?o2
WHERE
{
  GRAPH <urn:termsList/>
  { 
    ?term1 a <urn:types/word> . # outer loop variable
    ?term2 a <urn:types/word> . # inner loop variable
  }
  GRAPH <urn:associations/>
  {
    {
      # Only need to check one direction; either end gets 
      # matched into ?term1 at some point
      ?term1 ?p1 ?term2 .
      BIND (?term1 AS ?s1) .
      BIND (?term2 AS ?o1) . # Note we leave ?s2, ?p2, ?o2 unbound here
    }
    UNION
    { 
      ?term1 ?p1 ?term .
      ?term2 ?p2 ?term .
      FILTER(!SAMETERM(?term1, ?term2))
      BIND(?term1 AS ?s1) .
      BIND(?term AS ?o1) .
      BIND(?term2 AS ?s2) .
      BIND(?term AS ?o2)
    }
    UNION
    { 
      ?term1 ?p1 ?term .
      ?term ?p2 ?term2 .
      FILTER(!SAMETERM(?term1, ?term2))
      BIND(?term1 AS ?s1) .
      BIND(?term AS ?o1) .
      BIND(?term AS ?s2) .
      BIND(?term2 AS ?o2)
    }
    UNION
    { 
      ?term ?p1 ?term1 .
      ?term ?p2 ?term2 .
      FILTER(!SAMETERM(?term1, ?term2))
      BIND(?term AS ?s1) .
      BIND(?term1 AS ?o1) .
      BIND(?term AS ?s2) .
      BIND(?term2 AS ?o2)
    }
  }
}
# For God so loved the world, that he gave his only begotten Son, that 
# whosoever believeth in him should not perish, but have everlasting life.
# John 3:16

@prefix : <urn:terms/> .
@prefix t: <urn:types/> .

:For a t:word .
:God a t:word .
:so a t:word .
:loved a t:word .
:the a t:word .
:world a t:word .
:that a t:word .
:he a t:word .
:gave a t:word .
:his a t:word .
:only a t:word .
:begotten a t:word .
:Son a t:word .
:that a t:word .
:whosoever a t:word .
:believeth a t:word .
:in a t:word .
:him a t:word .
:should a t:word .
:not a t:word .
:perish a t:word .
:but a t:word .
:have a t:word .
:everlasting a t:word .
:life a t:word .
# For the wages of sin is death; but the gift of God is eternal life through 
# Jesus Christ our Lord.
# Romans 6:23

@prefix : <urn:terms/> .
@prefix g: <urn:grammar/> .

:For g:clauseAt :wages ;
     g:nextClauseHeadAt :but .
:the g:describes :wages .
:wages g:predicate :is .
:of g:describes :wages ;
    g:nominative :sin .
:is g:object :death .

:but g:clauseAt :gift .
:the g:describes :gift .
:gift g:predicate :is .
:of g:describes :gift ;
    g:nominative :God .
:is g:object :life .
:eternal g:describes :life .
:through g:describes :is ;
         g:nominative :Jesus .
:Christ g:describes :Jesus .
:our g:describes :Lord .
:Lord g:describes :Jesus .
----------------------------------------------------------------------------
| s                   | p                              | o                 |
============================================================================
| <urn:terms/For>     | <urn:grammar/nextClauseHeadAt> | <urn:terms/but>   |
| <urn:terms/For>     | <urn:grammar/clauseAt>         | <urn:terms/wages> |
| <urn:terms/of>      | <urn:grammar/nominative>       | <urn:terms/God>   |
| <urn:terms/is>      | <urn:grammar/object>           | <urn:terms/life>  |
| <urn:terms/eternal> | <urn:grammar/describes>        | <urn:terms/life>  |
| <urn:terms/but>     | <urn:grammar/clauseAt>         | <urn:terms/gift>  |
| <urn:terms/For>     | <urn:grammar/nextClauseHeadAt> | <urn:terms/but>   |
| <urn:terms/the>     | <urn:grammar/describes>        | <urn:terms/gift>  |
| <urn:terms/the>     | <urn:grammar/describes>        | <urn:terms/wages> |
----------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------------------------------------------
| s1              | p1                             | o1                | s2              | p2                      | o2                |
========================================================================================================================================
| <urn:terms/For> | <urn:grammar/nextClauseHeadAt> | <urn:terms/but>   |                 |                         |                   |
| <urn:terms/For> | <urn:grammar/clauseAt>         | <urn:terms/wages> | <urn:terms/the> | <urn:grammar/describes> | <urn:terms/wages> |
| <urn:terms/but> | <urn:grammar/clauseAt>         | <urn:terms/gift>  | <urn:terms/the> | <urn:grammar/describes> | <urn:terms/gift>  |
| <urn:terms/the> | <urn:grammar/describes>        | <urn:terms/wages> | <urn:terms/For> | <urn:grammar/clauseAt>  | <urn:terms/wages> |
| <urn:terms/the> | <urn:grammar/describes>        | <urn:terms/gift>  | <urn:terms/but> | <urn:grammar/clauseAt>  | <urn:terms/gift>  |
----------------------------------------------------------------------------------------------------------------------------------------
SELECT DISTINCT ?s1 ?p1 ?o1