web-dev-qa-db-ja.com

制限付きのサブクエリを使用するSPARQL

TDB上でFusekiエンドポイントを使用してARQを使用してSPARQLクエリを実行するJavaアプリケーションを開発しています。

アプリケーションには、各人と同じ場所で生まれた他の人の出生地を返すクエリが必要です。

まず、person_idsと各人の出生地を返すこのSPARQLクエリを作成しました。

prefix fb: <http://rdf.freebase.com/ns/>
prefix fn: <http://www.w3.org/2005/xpath-functions#>
select ?person_id ?place_of_birth 
where {
    ?person_id fb:type.object.type fb:people.person .
    ?person_id fb:people.person.place_of_birth ?place_of_birth_id .
    ?place_of_birth_id fb:type.object.name ?place_of_birth .
     FILTER (langMatches(lang(?place_of_birth),"en"))
}
LIMIT 10

----------------------------------
| person_id    | place_of_birth  |
==================================
| fb:m.01vtj38 | "El Centro"@en  |
| fb:m.01vsy7t | "Brixton"@en    |
| fb:m.09prqv  | "Pittsburgh"@en |
----------------------------------

その後、サブクエリを追加しました( https://jena.Apache.org/documentation/query/sub-select.html )そこで生まれた他の人を追加しましたが、複数の人がいます関連していて、必要なのは1つだけです。

prefix fb: <http://rdf.freebase.com/ns/>
prefix fn: <http://www.w3.org/2005/xpath-functions#>
select ?person_id ?place_of_birth ?other_person_id
where {
    ?person_id fb:type.object.type fb:people.person .
    ?person_id fb:people.person.place_of_birth ?place_of_birth_id .
    ?place_of_birth_id fb:type.object.name ?place_of_birth .
    {
       select  ?other_person_id
       where {
       ?place_of_birth_id fb:location.location.people_born_here ?other_person_id .
       }
     }
     FILTER (langMatches(lang(?place_of_birth),"en"))
}
LIMIT 10

---------------------------------------------------
| person_id    | place_of_birth | other_person_id |
===================================================
| fb:m.01vtj38 | "El Centro"@en | fb:m.01vtj38    |
| fb:m.01vtj38 | "El Centro"@en | fb:m.01vsy7t    |
| fb:m.01vtj38 | "El Centro"@en | fb:m.09prqv     |
---------------------------------------------------

LIMIT 1サブクエリを追加しようとしましたが、機能しないようです(クエリは実行されますが、終了しません)

prefix fb: <http://rdf.freebase.com/ns/>
prefix fn: <http://www.w3.org/2005/xpath-functions#>
select ?person_id ?place_of_birth ?other_person_id
where {
    ?person_id fb:type.object.type fb:people.person .
    ?person_id fb:people.person.place_of_birth ?place_of_birth_id .
    ?place_of_birth_id fb:type.object.name ?place_of_birth .
    {
       select  ?other_person_id
       where {
       ?place_of_birth_id fb:location.location.people_born_here ?other_person_id .
       }
       LIMIT 1
     }
     FILTER (langMatches(lang(?place_of_birth),"en"))
}
LIMIT 3

サブクエリで1つの結果のみを返す方法はありますか、またはSPARQLを使用してそれを行うことはできません。

11
Diego

サブクエリで制限を使用できます

サブクエリで制限を使用できます。次に例を示します。

select ?x ?y where {
  values ?x { 1 2 3 4 }
  {
    select ?y where {
      values ?y { 5 6 7 8 }
    }
    limit 2
  }
}
limit 5
---------
| x | y |
=========
| 1 | 5 |
| 1 | 6 |
| 2 | 5 |
| 2 | 6 |
| 3 | 5 |
---------

ご覧のとおり、サブクエリから2つの値(5と6)を取得し、これらを外部クエリからのバインディングと組み合わせて、合計5行を取得します(制限があるため)。

サブクエリは最も内側から最初に評価されます

ただし、サブクエリは最も内側から最も外側に向かって評価されることに注意してください。つまり、クエリでは、

select ?person_id ?place_of_birth ?other_person_id
where {
    ?person_id fb:type.object.type fb:people.person .
    ?person_id fb:people.person.place_of_birth ?place_of_birth_id .
    ?place_of_birth_id fb:type.object.name ?place_of_birth .
    {
       select  ?other_person_id
       where {
       ?place_of_birth_id fb:location.location.people_born_here ?other_person_id .
       }
       LIMIT 1
     }
     FILTER (langMatches(lang(?place_of_birth),"en"))
}
LIMIT 3

あなたは1つの一致を見つけています

?place_of_birth_id fb:location.location.people_born_here ?other_person_id .

?other_person_idバインディングoutを外部クエリに渡します。ただし、外部クエリの残りの部分は?other_person_idを使用しないため、結果には実際には影響しません。

代わりに何をすべきか

他に1人だけ必要な場合

アプリケーションには、各人と同じ場所で生まれた他の人の出生地を返すクエリが必要です。

概念的には、これは人を選び、出生地を見つけ、その場所で生まれた人からもう1人をサンプリングすることと見なすことができます。実際には、次のようなクエリを作成することもできます。

select ?person_id ?place_of_birth (sample(?other_person_idx) as ?other_person_id)
where {
    ?person_id fb:type.object.type fb:people.person .
    ?person_id fb:people.person.place_of_birth ?place_of_birth_id .
    ?place_of_birth_id fb:type.object.name ?place_of_birth .
    FILTER (langMatches(lang(?place_of_birth),"en"))
    ?place_of_birth_id fb:location.location.people_born_here ?other_person_idx .
    filter ( ?other_person_idx != ?person_id )
}
group by ?person_id ?place_of_birth

複数必要な場合

結果ごとに複数の「その他の結果」が必要な場合、これは非常に難しい問題です。それが 制限付きのsparqlにネストされたクエリ の問題です。 SPARQLソリューショングループのサイズを制限する方法は? にこれに使用できるアプローチがあります。

19
Joshua Taylor