9

私は SPARQL を初めて使用し、パスに沿って各中間ステップを吐き出すプロパティ パス クエリを作成しようとしています。これまでのところ、私はこれを持っています:

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

これにより、関係がどれほど離れていても、パス全体でサブジェクト URI とのすべての関係のリストが得られます (これまでに間違っていた場合は訂正してください)。

しかし、関係がどのように構成されているかを確認したいと思います。何かのようなもの:

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

など...これは可能ですか?

4

2 に答える 2

8

プロパティ パスでできることにはいくつかの制限がありますが、正確な要件によっては、ここで必要なものを取得できる場合があります。次のデータを検討してください。

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

3 つの: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)

順番にエッジを取得することが保証されます。

于 2013-08-03T10:49:14.713 に答える
5

いいえ、これはプロパティ パスの設計上の制限です。

パスは、より複雑なクエリ パターンを圧縮するために使用するか、例のように任意の長さのパスをテストするために使用できます。

前者は、中間ステップを提供する形式に変換できます。

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
}

すぐにわかるように、これは非常に冗長になります。

于 2013-08-02T20:57:07.300 に答える