Пока есть 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)
и гарантированно получить ваши края в последовательности.
Только что увидел уведомление для этого, извините! Я не продвинулся дальше, чем в комментариях ниже. В настоящий момент проект приостановлен, но я надеюсь скоро вернуться к нему! – bdkauff