Virtuoso OpenLink: находка, если два узла подключены на определенном расстоянии
Вопрос
Как я могу найти расстояние между 2 узлами в графике с использованием Virtuoso? Я прочитал документацию по проходности, но они ограничивают вас одним предикатом, например:
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
И не какой-то тип предиката. Как я могу продлить это как «все, что предикат»? Мне не нужен фактический путь, просто настоящий / ложный (запросить запрос). Изменение оказания: знает? P кажется сверху.
В настоящее время я выполняю набор рекурсивных просит выяснить, подключены ли два узла на определенном расстоянии, но не кажется эффективным.
Решение
Вы должны быть в состоянии использовать ?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
Другие советы
Вот подход, который работает, если между узлами вас интересуют один путь. Если у вас есть такие данные (обратите внимание, что есть разные свойства, соединяющие ресурсы):
@prefix : <https://stackoverflow.com/q/3914522/1281433/>
:a :p :b .
:b :q :c .
:c :r :d .
Затем запрос, как следующее, находит расстояние между каждой парой узлов. Путь к недвижимости (:|!:)
состоит имущество, которое является либо :
или что-то другое, чем :
(то есть что-нибудь). Таким образом (:|!:)*
равен нулю или более вхождению любого свойства; Это тропинка подстановки. (Техника, используемая здесь, описана более полностью в Можно ли получить позицию элемента в коллекции RDF в Sparql?.)
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 |
--------------------------
Просто выяснить, есть ли путь между двумя узлами, которым меньше, чем какая-то конкретная длина, вы используете ask
запрос вместо select
, исправьте значения ?begin
и ?end
, и ограничить ценность count(?mid)-1
а не привязывать его к ?distance
. Отказ Например, есть ли путь от :a
к :d
длина менее трех?
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