用相关语句中的值替换三个节点

时间:2013-11-30 10:23:40

标签: rdf sparql

考虑以下陈述:

:id1 :id2 "1942"
:id1 :hasName "Dan"
:id2 :hasName "Born"
:id3 :id4 "50"

我想要一个输出的查询:

"Dan" "Born" "1942"
"Dan" :hasName "Dan"
"Born" :hasName "Born"
:id3 :id4 "50"

因此,无论何时发现一个语句中的节点都有另一个带有“:hasName”谓词的语句,它都会用该语句中的值替换它。

我怎么能改善 查询输出:

:id1/Dan :id2/Born "1942"
:id1/Dan :hasName "Dan"
:id2/Born :hasName "Born"
:id3 :id4 "50"

1 个答案:

答案 0 :(得分:1)

由于使用完整的数据集更容易,让我们为您的数据提供一个前缀,以便您拥有:

@prefix : <http://stackoverflow.com/q/20299083/1281433/>

:id1 :id2 "1942" ;
     :hasName "Dan" .
:id2 :hasName "Born" ;
     :id4 "50" .

现在,您是否正在尝试选择主题,谓词和对象来获取所需的输出,或者您是否尝试构建 em>图表。让我们首先使用select来获取我们想要的值,然后我们可以担心将它们组合成一个图形。像这样的查询是一个很好的起点:

prefix : <http://stackoverflow.com/q/20299083/1281433/>

select ?s ?p ?o where { 
  ?s ?p ?o .
}

其结果是:

----------------------------
| s    | p        | o      |
============================
| :id3 | :id4     | "50"   |
| :id2 | :hasName | "Born" |
| :id1 | :hasName | "Dan"  |
| :id1 | :id2     | "1942" |
----------------------------

现在,您想说如果?s?p具有:hasName属性(可选),那么您希望在结果中使用它。您可以添加模式以提取这些名称,然后select使用coalesce(?sName,?sx) as ?s之类的内容(如果可用),并使用?sx

prefix : <http://stackoverflow.com/q/20299083/1281433/>

select (coalesce(?sName,?sx) as ?s)
       (coalesce(?pName,?px) as ?p)
       ?o
where { 
  ?sx ?px ?o
  optional { ?sx :hasName ?sName }
  optional { ?px :hasName ?pName }
}

请注意,结果只能称为伪RDF,因为在RDF中,文字(例如字符串)不能成为三元组的主题,因此并非所有?s的值都可以成为主题。但是,如果您手动处理结果集,则可以。也就是说,结果是你最初要求的结果:

------------------------------
| s      | p        | o      |
==============================
| :id3   | :id4     | "50"   |
| "Born" | :hasName | "Born" |
| "Dan"  | :hasName | "Dan"  |
| "Dan"  | "Born"   | "1942" |
------------------------------

现在,我们真的想要一个IRI,而不是使用?s?p字符串表单。我们需要做的就是使用str获取IRI的字符串形式,使用concat将它们与名称连接起来,然后将IRI将结果字符串转换为IRI:

prefix : <http://stackoverflow.com/q/20299083/1281433/>

select (coalesce(iri(concat(str(?sx),"/",?sName)),?sx) as ?s)
       (coalesce(iri(concat(str(?px),"/",?pName)),?px) as ?p)
       ?o
where { 
  ?sx ?px ?o
  optional { ?sx :hasName ?sName }
  optional { ?px :hasName ?pName }
}
----------------------------------------------------------------------------------------------------------------------------
| s                                                      | p                                                      | o      |
============================================================================================================================
| :id3                                                   | :id4                                                   | "50"   |
| <http://stackoverflow.com/q/20299083/1281433/id2/Born> | :hasName                                               | "Born" |
| <http://stackoverflow.com/q/20299083/1281433/id1/Dan>  | :hasName                                               | "Dan"  |
| <http://stackoverflow.com/q/20299083/1281433/id1/Dan>  | <http://stackoverflow.com/q/20299083/1281433/id2/Born> | "1942" |
----------------------------------------------------------------------------------------------------------------------------

此表单非常长,并且IRI似乎没有缩短前缀,因为/不能出现在名称部分中。如果你使用不同的分隔符(例如-),你可以得到更短的结果:

prefix : <http://stackoverflow.com/q/20299083/1281433/>

select (coalesce(iri(concat(str(?sx),"-",?sName)),?sx) as ?s)
       (coalesce(iri(concat(str(?px),"-",?pName)),?px) as ?p)
       ?o
where { 
  ?sx ?px ?o
  optional { ?sx :hasName ?sName }
  optional { ?px :hasName ?pName }
}
----------------------------------
| s         | p         | o      |
==================================
| :id3      | :id4      | "50"   |
| :id2-Born | :hasName  | "Born" |
| :id1-Dan  | :hasName  | "Dan"  |
| :id1-Dan  | :id2-Born | "1942" |
----------------------------------

最后,如果您想获得包含这些三元组的RDF图表,您可能希望将这些coalesce(… as …)表达式推送到where模式中bind。 (您也可以在前面的示例中执行此操作,也可以执行select ?s ?p ?o。这只是一个品味问题。)

prefix : <http://stackoverflow.com/q/20299083/1281433/>

construct {
  ?s ?p ?o
} 
where { 
  ?sx ?px ?o
  optional { ?sx :hasName ?sName }
  optional { ?px :hasName ?pName }
  bind(coalesce(iri(concat(str(?sx),"-",?sName)),?sx) as ?s)
  bind(coalesce(iri(concat(str(?px),"-",?pName)),?px) as ?p)
}

在Turtle中,结果是:

@prefix :      <http://stackoverflow.com/q/20299083/1281433/> .

:id1-Dan  :hasName  "Dan" ;
          :id2-Born "1942" .

:id3      :id4      "50" .

:id2-Born :hasName  "Born" .

在RDF / XML中:

<rdf:RDF
    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
    xmlns="http://stackoverflow.com/q/20299083/1281433/">
  <rdf:Description rdf:about="http://stackoverflow.com/q/20299083/1281433/id2-Born">
    <hasName>Born</hasName>
  </rdf:Description>
  <rdf:Description rdf:about="http://stackoverflow.com/q/20299083/1281433/id3">
    <id4>50</id4>
  </rdf:Description>
  <rdf:Description rdf:about="http://stackoverflow.com/q/20299083/1281433/id1-Dan">
    <hasName>Dan</hasName>
    <id2-Born>1942</id2-Born>
  </rdf:Description>
</rdf:RDF>