我是SPARQL的新手,我正在尝试创建一个属性路径查询,它将沿路径吐出每个中间步骤。到目前为止,我有这个:
select ?object
where {
<subjectURI> <isRelatedTo>+ ?object .
}
这给了我一个列表,列出了整个路径中我的主题URI的所有关系,无论关系有多远(如果我错了,请纠正我)。
但是,我想看看关系是如何组织起来的。类似的东西:<subjectURI> <isRelatedTo> <object1>
<object1> <isRelatedTo> <object2>
<object2> <isRelatedTo> <object3>
依此类推......这可能吗?
答案 0 :(得分:5)
虽然属性路径可以some limitations,但根据您的具体要求,您可以在此处获得所需内容。考虑这些数据:
@prefix : <urn:ex:>.
:a :relatedTo :b .
:b :relatedTo :c .
:c :relatedTo :d .
:a :relatedTo :e .
:e :relatedTo :f .
:f :relatedTo :g .
:h :relatedTo :i .
:i :relatedTo :j .
:j :relatedTo :k .
:k :relatedTo :l .
其中有三条:relatedTo
路径:
a --> b --> c --> d
a --> e --> f --> g
h --> i --> j --> k --> l
我意识到在你的情况下,你有一个特定的主题,但我们可以稍微概括一下,并用这样的查询询问每个路径中的每个边缘:
prefix : <urn:ex:>
select * where {
# start a path
?begin :relatedTo* ?midI .
FILTER NOT EXISTS { [] :relatedTo ?begin }
# grab next edge
?midI :relatedTo ?midJ .
# get to the end of the path.
?midJ :relatedTo* ?end .
FILTER NOT EXISTS { ?end :relatedTo [] }
}
order by ?start ?end
$ arq --data data.n3 --query query.sparql
-----------------------------
| begin | midI | midJ | end |
=============================
| :a | :a | :b | :d |
| :a | :b | :c | :d |
| :a | :c | :d | :d |
| :a | :a | :e | :g |
| :a | :e | :f | :g |
| :a | :f | :g | :g |
| :h | :h | :i | :l |
| :h | :i | :j | :l |
| :h | :j | :k | :l |
| :h | :k | :l | :l |
-----------------------------
显示每个:relatedTo
路径的每个边缘。你也可以使输出更漂亮一点:
prefix : <urn:ex:>
select (concat(str(?begin),"--",str(?end)) as ?path) ?midI ?midJ where {
# start a path
?begin :relatedTo* ?midI .
FILTER NOT EXISTS { [] :relatedTo ?begin }
# grab next edge
?midI :relatedTo ?midJ .
# get to the end of the path.
?midJ :relatedTo* ?end .
FILTER NOT EXISTS { ?end :relatedTo [] }
}
order by ?path
$ arq --data data.n3 --query query.sparql
--------------------------------------
| path | midI | midJ |
======================================
| "urn:ex:a--urn:ex:d" | :a | :b |
| "urn:ex:a--urn:ex:d" | :b | :c |
| "urn:ex:a--urn:ex:d" | :c | :d |
| "urn:ex:a--urn:ex:g" | :a | :e |
| "urn:ex:a--urn:ex:g" | :e | :f |
| "urn:ex:a--urn:ex:g" | :f | :g |
| "urn:ex:h--urn:ex:l" | :h | :i |
| "urn:ex:h--urn:ex:l" | :i | :j |
| "urn:ex:h--urn:ex:l" | :j | :k |
| "urn:ex:h--urn:ex:l" | :k | :l |
--------------------------------------
这种方法可以让你做一些有趣的事情,比如找出某些节点分开的距离:
prefix : <urn:ex:>
select ?begin ?end (count(*) as ?length) where {
# start a path
?begin :relatedTo* ?midI .
FILTER NOT EXISTS { [] :relatedTo ?begin }
# grab next edge
?midI :relatedTo ?midJ .
# get to the end of the path.
?midJ :relatedTo* ?end .
FILTER NOT EXISTS { ?end :relatedTo [] }
}
group by ?begin ?end
------------------------
| begin | end | length |
========================
| :a | :g | 3 |
| :a | :d | 3 |
| :h | :l | 4 |
------------------------
在我上面提供的数据中,路径恰好按字母顺序排列,因此排序以正确的顺序产生边缘。但是,即使边缘节点不是按字母顺序排列的,我们仍然可以通过计算它们在列表中的位置来按顺序打印它们。这个查询:
prefix : <urn:ex:>
select ?begin ?midI ?midJ (count(?counter) as ?position) ?end where {
?begin :relatedTo* ?counter .
?counter :relatedTo* ?midI .
FILTER NOT EXISTS { [] :relatedTo ?begin }
?midI :relatedTo ?midJ .
?midJ :relatedTo* ?end .
FILTER NOT EXISTS { ?end :relatedTo [] }
}
group by ?begin ?end ?midI ?midJ
----------------------------------
| begin | midI | midJ | .1 | end |
==================================
| :a | :a | :b | 1 | :d |
| :a | :b | :c | 2 | :d |
| :a | :c | :d | 3 | :d |
| :a | :a | :e | 1 | :g |
| :a | :e | :f | 2 | :g |
| :a | :f | :g | 3 | :g |
| :h | :h | :i | 1 | :l |
| :h | :i | :j | 2 | :l |
| :h | :j | :k | 3 | :l |
| :h | :k | :l | 4 | :l |
----------------------------------
我们没有必要看那个数,但你可以,而不是选择位置,你可以用它作为排序条件:
prefix : <urn:ex:>
select ?begin ?midI ?midJ ?end
where {
?begin :relatedTo* ?counter .
?counter :relatedTo* ?midI .
FILTER NOT EXISTS { [] :relatedTo ?begin }
?midI :relatedTo ?midJ .
?midJ :relatedTo* ?end .
FILTER NOT EXISTS { ?end :relatedTo [] }
}
group by ?begin ?end ?midI ?midJ
order by ?begin ?end count(?counter)
并保证按顺序获得你的优势。
答案 1 :(得分:3)
不,这是属性路径设计的限制。
路径可以用于压缩更复杂的查询模式,也可以用于测试任意长度的路径,如示例所示。
前者可以转换为一种形式,为您提供中间步骤,例如
SELECT * WHERE
{
?s <http://predicate>/<http://predicate> ?o
}
可以转换为以下内容:
SELECT * WHERE
{
?s <http://predicate> ?intermediate .
?intermediate <http://predicate> ?o .
}
不幸的是,对于任意长度的路径都不能做同样的事情。但是,如果您知道路径的上限是什么,则可以像这样重写查询:
SELECT *
WHERE
{
{
?s <http://predicate> ?step1 .
?step1 <http://predicate> ?o .
}
UNION
{
?s <http://predicate> ?step1 .
?step1 <http://predicate> ?step2 .
?step2 <http://predicate> ?o .
}
# Add additional UNION for each length of path you want up to your upper bound
}
虽然你可以立即看到这让事情变得非常冗长。