プロパティ パスでできることにはいくつかの制限がありますが、正確な要件によっては、ここで必要なものを取得できる場合があります。次のデータを検討してください。
@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 .
3 つの: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)
順番にエッジを取得することが保証されます。