OpenLink Virtuoso:特定の距離内に2つのノードが接続されているかどうかを見つける
質問
Virtuosoを使用してグラフ内の2つのノード間の距離を見つけるにはどうすればよいですか?私は推移性のドキュメントを読みましたが、それらはあなたを1つの述語に制限します。
SELECT ?link ?g ?step ?path
WHERE
{
{
SELECT ?s ?o ?g
WHERE
{
graph ?g {?s foaf:knows ?o }
}
} OPTION (TRANSITIVE, t_distinct, t_in(?s), t_out(?o), t_no_cycles, T_shortest_only,
t_step (?s) as ?link, t_step ('path_id') as ?path, t_step ('step_no') as ?step, t_direction 3) .
FILTER (?s= <http://www.w3.org/People/Berners-Lee/card#i>
&& ?o = <http://www.advogato.org/person/mparaz/foaf.rdf#me>)
}
LIMIT 20
トラバースのみ foaf:knows
述語タイプではありません。これを「どんな述語」に拡張できますか?実際のパスは必要ありません。ただの/false(クエリに質問)。フォーフを変更する:pを知っている?pはやり過ぎのように思えます。
私は現在、特定の距離内で2つのノードが接続されているかどうかを調べるために一連の再帰的な要求を行っていますが、それは効率的ではないようです。
解決
使用できるはずです ?p
それ以外の foaf:knows
クエリで、ノード間にパスがあるかどうかを判断します。例えば:
SELECT ?link ?g ?step ?path
WHERE
{
{
SELECT ?s ?o ?g
WHERE
{
graph ?g {?s ?p ?o }
}
} OPTION (TRANSITIVE, t_distinct, t_in(?s), t_out(?o), t_no_cycles, T_shortest_only,
t_step (?s) as ?link, t_step ('path_id') as ?path, t_step ('step_no') as ?step, t_direction 3) .
FILTER (?s= <http://www.w3.org/People/Berners-Lee/card#i>
&& ?o = <http://www.advogato.org/person/mparaz/foaf.rdf#me>)
}
LIMIT 20
他のヒント
興味のあるノードの間にせいぜい1つのパスがある場合に機能するアプローチは次のとおりです。このようなデータがある場合(リソースを接続する異なるプロパティがあることに注意してください):
@prefix : <https://stackoverflow.com/q/3914522/1281433/>
:a :p :b .
:b :q :c .
:c :r :d .
次に、次のようなクエリで、ノードの各ペア間の距離が見つかります。プロパティパス (:|!:)
どちらかのプロパティが構成されています :
または以外の何か :
(つまり、何でも)。したがって (:|!:)*
任意のプロパティのゼロ以上の発生です。ワイルドカードの道です。 (ここで使用される手法は、より完全に説明されています SPARQLのRDFコレクションで要素の位置を取得することは可能ですか?.)
prefix : <https://stackoverflow.com/q/3914522/1281433/>
select ?begin ?end (count(?mid)-1 as ?distance) where {
?begin (:|!:)* ?mid .
?mid (:|!:)* ?end .
}
group by ?begin ?end
order by ?begin ?end ?distance
--------------------------
| begin | end | distance |
==========================
| :a | :a | 0 |
| :a | :b | 1 |
| :a | :c | 2 |
| :a | :d | 3 |
| :b | :b | 0 |
| :b | :c | 1 |
| :b | :d | 2 |
| :c | :c | 0 |
| :c | :d | 1 |
| :d | :d | 0 |
--------------------------
特定の長さよりも少ない2つのノード間にパスがあるかどうかを確認するために、 ask
aの代わりにクエリ select
, 、の値を修正します ?begin
と ?end
, 、およびの値を制限します count(?mid)-1
に結合するのではなく ?distance
. 。たとえば、から道があります :a
に :d
3未満の長さ?
prefix : <https://stackoverflow.com/q/3914522/1281433/>
ask {
values (?begin ?end) { (:a :d) }
?begin (:|!:)* ?mid .
?mid (:|!:)* ?end .
}
group by ?begin ?end
having ( (count(?mid)-1 < 3 ) )
Ask => No
一方、からの道があります :a
に :c
5未満の長さ:
prefix : <https://stackoverflow.com/q/3914522/1281433/>
ask {
values (?begin ?end) { (:a :c) }
?begin (:|!:)* ?mid .
?mid (:|!:)* ?end .
}
group by ?begin ?end
having ( (count(?mid)-1 < 5 ) )
Ask => Yes