2013-08-02 12 views
5

Jestem nowy w SPARQL i próbuję utworzyć zapytanie ścieżki właściwości, które wypluje każdy etap pośredni wzdłuż ścieżki. Do tej pory mam to:Znajdowanie wszystkich kroków w ścieżce właściwości

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

To daje mi listę wszystkich relacji do mojego tematu URI całej ścieżce, bez względu na to jak daleko relacja (poprawcie mnie jeśli się mylę do tej pory).

Ale chciałbym zobaczyć, jak układają się relacje. Coś jak:

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

i tak dalej ... Czy to możliwe?

+0

Właśnie zobaczyłem powiadomienie, przepraszam! Nie zrobiłem żadnego postępu poza tym, co jest w komentarzach poniżej. Projekt jest w tej chwili wstrzymany, ale mam nadzieję, że wkrótce do niego wrócę! – bdkauff

Odpowiedz

2

Nie, to ograniczenie projektowania ścieżek własności.

Ścieżki mogą być też stosowane do zagęszczania bardziej skomplikowanych wzorów zapytań lub mogą być wykorzystywane do testowania dowolnych ścieżek długości, jak w przykładzie.

Ten pierwszy może zostać przekształcony w formularz, który daje kroki pośrednie, np.

SELECT * WHERE 
{ 
    ?s <http://predicate>/<http://predicate> ?o 
} 

Może być przekształcone do następujących:

SELECT * WHERE 
{ 
    ?s <http://predicate> ?intermediate . 
    ?intermediate <http://predicate> ?o . 
} 

Niestety tego samego nie można zrobić dla dowolnych ścieżek długości. Jednakże, jeśli wiesz, co górna granica na ścieżkach są można przepisać zapytanie tak:

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 
} 

choć jak można od razu zobaczyć to sprawia, że ​​rzeczy bardzo gadatliwy.

+0

Dzięki! Myślę, że pamiętam, że czytałem o tym ograniczeniu. Rozwiązanie jest pełne, ale prawdopodobnie mniej, niż próba odtworzenia postprocesora w chmielu. – bdkauff

+1

@ user2350906 Chociaż istnieją pewne ograniczenia co do sposobów, które można wykonać za pomocą ścieżek właściwości, myślę, że można uzyskać informacje, których szukasz, korzystając z kwerendy, która używa ścieżek właściwości, i opisałem to w [odpowiedź] (http://stackoverflow.com/a/18032019/1281433). –

4

Chociaż istnieje some limitations w zależności od konkretnych wymagań, może być możliwe uzyskanie tego, czego potrzebujesz. Rozważmy te dane:

@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 . 

w którym istnieją trzy :relatedTo ścieżki:

a --> b --> c --> d 
a --> e --> f --> g 
h --> i --> j --> k --> l 

Zdaję sobie sprawę, że w przypadku, miałeś konkretny temat, ale możemy uogólniać trochę, i poprosić o każda krawędź każdego z tych ścieżek z zapytania, jak poniżej:

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 | 
----------------------------- 

, która pokazuje każdą krawędź każdej ścieżki :relatedTo.Można zrobić wyjście trochę ładniejsza, zbyt:

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 | 
-------------------------------------- 

To samo podejście pozwoli zrobić kilka ciekawych rzeczy, jak dowiedzieć się, jak daleko oddzielone niektóre węzły są:

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  | 
------------------------ 

W podanych przeze mnie danych ścieżki znajdują się w porządku alfabetycznym, a więc sortowanie tworzy krawędzie we właściwej kolejności. Jednak nawet jeśli węzły krawędzi nie są alfabetyczne, możemy je wydrukować w kolejności, obliczając ich pozycję na liście. To zapytanie:

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 | 
---------------------------------- 

Robimy nie konieczną potrzebę zobaczyć że liczyć, ale można zamiast wybierania pozycji, można go używać jako warunek Sortowanie:

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) 

i mieć pewność, aby uzyskać krawędzie w kolejności.

+0

Dziękuję za odpowiedź. To, co sugerujesz, działa do pewnego momentu, ale gdy dodaję więcej niż kilka kroków, zapytanie odpowiada bez odpowiedzi. Zgodnie z tym zapytaniem: 'wybierz? X (COUNT (? Z) AS? LinkTotal) gdzie { ? X: relatedTo +? Z. } grupa przez AX HAVING COUNT (? (X)> 1) ' dostaję max wartość 12. Nie oznacza to, że najdłuższy najkrótsza ścieżka jest 12 stopni, a więc powinien być w stanie dodać 12 (err, 10?) pośrednich kroków do zapytania i nadal uzyskać jeden pasujący przypadek? – bdkauff

+0

@ user2350906 Nie widząc twoich danych, trudno jest określić, co zwróci zapytanie. Zauważam jednak, że używasz '+', którego nie użyłem w żadnym z moich zapytań. '+" oznacza jeden lub więcej, podczas gdy '*' wynosi 0 lub więcej. –

+0

@ user2350906 Czy możesz już to rozwinąć? Różnica między '+' jest znacząca, a jeśli grupujesz według '? X', powinna ona mieć klauzulę' HAVING '(COUNT (? Z)> 1) zamiast 'HAVING COUNT (? X)> 1) '(tj. Liczyć'? Z', a nie '? Y')? –

Powiązane problemy