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