2013-08-02 2 views
5

Я новичок в SPARQL, и я пытаюсь создать запрос пути свойства, который выплюнет каждый промежуточный шаг по пути. До сих пор у меня есть это:Поиск всех шагов в пути свойств

select ?object 
where { 
    <subjectURI> <isRelatedTo>+ ?object . 
} 

Это дает мне список всех отношений к моей теме URI по всему пути, независимо от того, насколько отдаленное отношение (поправьте меня, если я ошибаюсь, до сих пор).

Но я хотел бы посмотреть, как организованы отношения. Что-то вроде:

<subjectURI> <isRelatedTo> <object1> 
<object1> <isRelatedTo> <object2> 
<object2> <isRelatedTo> <object3> 

и так далее ... Возможно ли это?

+0

Только что увидел уведомление для этого, извините! Я не продвинулся дальше, чем в комментариях ниже. В настоящий момент проект приостановлен, но я надеюсь скоро вернуться к нему! – bdkauff

ответ

2

Нет, это ограничение дизайна путей собственности.

Пути могут использоваться для уплотнения более сложных шаблонов запросов или их можно использовать для проверки произвольных путей длины, как в вашем примере.

Первый может быть преобразован в форму, которая дает вам промежуточные этапы, например.

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 
} 

Хотя, как вы можете сразу увидеть это делает вещи очень многословны.

+0

Спасибо! Кажется, я вспоминаю об этом ограничении. Решение является многословным, но, вероятно, меньше, чем попытка реконструировать post-query hops. – bdkauff

+1

@ user2350906 Хотя есть некоторые ограничения на то, что вы можете делать с путями свойств, я думаю, вы можете получить информацию, которую вы ищете, из запроса, который использует пути свойств, и я описал его в [ответе] (http://stackoverflow.com/a/18032019/1281433). –

4

Пока есть 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) 

и гарантированно получить ваши края в последовательности.

+0

Благодарим за отзыв. То, что вы предлагаете, работает до определенной степени, но поскольку я добавляю несколько шагов, запрос отвечает ничем. По этому запросу: 'select? X (COUNT (? Z) AS? LinkTotal) где { ? X: relatedTo +? Z. } группа по? Х HAVING (COUNT (? Х)> 1) ' я получаю максимальное значение 12. Не это означает, что самый длинный кратчайший путь 12 шагов, и поэтому я должен быть в состоянии добавить к вашему запросу 12 (ошибочных, 10?) промежуточных шагов и получить один подходящий случай? – bdkauff

+0

@ user2350906 Не видя ваших данных, трудно сказать, что ответ будет возвращен. Однако я замечаю, что вы используете '+', который я не использовал ни в одном из моих запросов. '+' означает один или несколько, тогда как '*' равно 0 или более. –

+0

@ user2350906 Можете ли вы подробнее рассказать об этом? Разница между '+' значительна, и если вы группируете '? X', должно ли это предложение' HAVING' быть 'HAVING (COUNT (? Z)> 1)', а не 'HAVING COUNT (? X)> 1) '(т. Е. Count'? Z', а не '? Y')? –

Смежные вопросы