考虑以下陈述:
: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"
答案 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>