2

私の同僚の 1 人は、用語の関連付けを含む 2 セットの RDF トリプルを取得する必要があります。用語はリストから取得され、関連付けはそれらの用語を使用する一連のトリプルから取得されます。

  • 最初のセットはすべてトリプルであり、ターム リスト内の任意の項目がトリプルの主語または目的語のいずれかになります。

  • 2 番目のセットはすべてトリプルであり、任意の 2 つの項は互いに離れた 1 つまたは 2 つの述語であり、述語は必ずしも双方向ではありません。したがって、用語リストの s1 と s2 に対して、2 つのトリプル s1 → s3 と s2 → s3 が有効になります。

すでに答えは出ていると思いますが、SPARQL ベースへの貢献と自分自身のチェックをお願いしたかったのです。

4

2 に答える 2

4

次のようなデータが与えられた場合:

@prefix : <urn:ex:> .

:a :p :b .
:a :p :e .

:b :p :c .
:b :p :d .

:c :p :a .
:c :p :f .

:d :p :a .
:d :p :d .

興味深い用語のセットとして、次のクエリを(:b :c)実行すると、関心のあるすべてのトリプルが検索されます。最初のセットの条件、つまり、. ターム リストにあるorの?s ?p ?oいずれかから、2 番目のセットの一部、つまり 2 つのタームが接続されている部分、つまり、 と の両方ターム リストにある部分も取得します。?s?o ?s?o

prefix : <urn:ex:>

select distinct ?s ?p ?between ?q ?o where { 
  # term list appearing twice in order to 
  # get all pairs of items
  values ?x { :b :c }
  values ?y { :b :c }

  # This handles the first set (where either the subject or
  # object is from the term list).  Note that the first set
  # includes part of the second set;  when two terms from 
  # the list are separated by just one predicate, then it's
  # a case where either the subject or object are from the
  # term list (since *both* are).
  { ?s ?p ?x bind(?x as ?o)} UNION { ?x ?p ?o bind(?x as ?s)}

  UNION 

  # The rest of the second set is when two terms from the
  # list are connected by a path of length two.  This is 
  # a staightforward pattern to write.
  { ?x ?p ?between . ?between ?q ?y .
    bind(?x as ?s)
    bind(?y as ?o) }
}

結果では、単一のトリプルは、sp、およびoのみがバインドされている行です。これらは、最初のセットと、2 番目のセットの「距離 = 1」の部分をカバーします。2 番目のセットの残りの部分も と をバインドbetweenqます。あなたの質問の例に関しては、betweenですs3

$ arq --data data.n3 --query query.sparql
-------------------------------
| s  | p  | between | q  | o  |
===============================
| :a | :p |         |    | :b |
| :b | :p |         |    | :d |
| :b | :p |         |    | :c |
| :c | :p |         |    | :f |
| :c | :p |         |    | :a |
| :c | :p | :a      | :p | :b |
-------------------------------

コメントに基づく更新

コメントの例を考えると、このクエリは次のように劇的に短縮できると思います。

prefix : <urn:ex:>

select distinct ?x ?p ?between ?q ?y where { 
  values ?x { :b :c }
  values ?y { :b :c }

  { ?x ?p ?between } UNION { ?between ?p ?x }
  { ?between ?q ?y } UNION { ?y ?q ?between }
}

?x ?p ?betweenorをバインドしたら、 と の間に?between ?p ?x(いずれかの方向に) エッジがあると言っているだけです。そのパスを拡張して、次のようにします。?x?between?y?q

?x --?p-- ?between --?q-- ?y

--?p--との実際の方向は--?q--左または右です。これで、必要なすべてのケースがカバーされます。長さ 2 のパスがこのパターンに一致する理由を理解するのはおそらく難しくありませんが、主語または目的語だけが特別な用語であるトリプルの場合は、詳しく説明する価値があります。トリプルを考える

<term> <prop> <non-term>

パスを取得できます

<term> --<prop>-- <non-term> --<prop>-- <term>

これは、それが目的語であり、主語である場合に機能し<term>ます<non-term>。また、主語と目的語の両方が用語である場合もカバーします。上記のデータでは、結果は次のとおりです。

$ arq --data data.n3 --query paths.sparql
-------------------------------
| x  | p  | between | q  | y  |
===============================
| :b | :p | :d      | :p | :b |   
| :b | :p | :c      | :p | :b |   
| :b | :p | :a      | :p | :b |
| :c | :p | :a      | :p | :b |
| :b | :p | :a      | :p | :c |
| :c | :p | :f      | :p | :c |
| :c | :p | :a      | :p | :c |
| :c | :p | :b      | :p | :c |
-------------------------------

?p?qが指している方向に関する情報を追加すると、パスを再構築できます。

prefix : <urn:ex:>

select distinct ?x ?p ?pdir ?between ?q ?qdir ?y where { 
  values ?x { :b :c }
  values ?y { :b :c }

  { ?x ?p ?between bind("right" as ?pdir)} UNION { ?between ?p ?x bind("left" as ?pdir)}
  { ?between ?q ?y bind("right" as ?qdir)} UNION { ?y ?q ?between bind("left" as ?qdir)}
}

これにより、次の出力が得られます。

$ arq --data data.n3 --query paths.sparql
---------------------------------------------------
| x  | p  | pdir    | between | q  | qdir    | y  |
===================================================
| :b | :p | "right" | :d      | :p | "left"  | :b |   # :b -> :d
| :b | :p | "right" | :c      | :p | "left"  | :b |   # :b -> :c 
| :b | :p | "left"  | :a      | :p | "right" | :b |   # :a -> :b 
| :c | :p | "right" | :a      | :p | "right" | :b |   # :c -> :a -> :b
| :b | :p | "left"  | :a      | :p | "left"  | :c |   # :c -> :a -> :b 
| :c | :p | "right" | :f      | :p | "left"  | :c |   # :c -> :f 
| :c | :p | "right" | :a      | :p | "left"  | :c |   # :c -> :a 
| :c | :p | "left"  | :b      | :p | "right" | :c |   # :b -> :c 
---------------------------------------------------

パスの繰り返しがありc -> a -> bますが、おそらく除外される可能性があります。

特定のパスではなく、実際にここでトリプルのセットを探している場合は、グラフを返す構成クエリを使用できます (トリプルのセットはグラフであるため)。

prefix : <urn:ex:>

construct {
  ?s1 ?p ?o1 .
  ?s2 ?q ?o2 .
}
where { 
  values ?x { :b :c }
  values ?y { :b :c }

  { ?x ?p ?between .
    bind(?x as ?s1)
    bind(?between as ?o1) }
  UNION
  { ?between ?p ?x .
    bind(?between as ?s1)
    bind(?x as ?o1)}

  { ?between ?q ?y .
    bind(?between as ?s2)
    bind(?y as ?o2) }
  UNION 
  { ?y ?q ?between .
    bind(?y as ?s2)
    bind(?between as ?o2)}
}
$ arq --data data.n3 --query paths-construct.sparql
@prefix :        <urn:ex:> .

<urn:ex:b>
      <urn:ex:p>    <urn:ex:c> ;
      <urn:ex:p>    <urn:ex:d> .

<urn:ex:c>
      <urn:ex:p>    <urn:ex:f> ;
      <urn:ex:p>    <urn:ex:a> .

<urn:ex:a>
      <urn:ex:p>    <urn:ex:b> .
于 2013-07-26T13:30:08.003 に答える