SPARQL入門

はじめに_

Wikipediaの構造化データ版サービスであるja.dbpediaWikidataを使って、RDF用クエリ言語のSPARQLの使い方を学ぶ。

SPARQL_

W3C勧告:RDF用クエリ言語SPARQLの和訳によると以下の通り。

SPARQLは、データがRDFそのものとして保存されているか、ミドルウェアを通してRDFとして見えるのかにかかわらず、さまざまなデータ情報源にまたがるクエリを表わすために使用できます。SPARQLには、必須および任意のグラフ・パターンをその論理積と論理和とともに問い合わせる性能が含まれています。SPARQLは、ソースRDFグラフによる拡張可能な値テストやクエリの制約もサポートします。SPARQLクエリの結果は、結果集合またはRDFグラフでありえます。

SPARQLの最新バージョンは1.1

dbpedia_

ja.dbpediaのトップページの説明より。

DBpediaはWikipediaから情報を抽出してLOD (Linked Open Data)として公開するコミュニティプロジェクトです.本家のDBpediaは主にWikipedia英語版を対象としています.DBpedia Japanese の目的は,Wikipedia日本語版を対象としたDBpediaを提供することです.

WikidataのRDF構造_

以下の資料の6~11ページを参照。

SPARQL基本構文_

SPARQLの文法(拡張BNF)はこちらで確認できる。一番よく使うSELECT文の基本的な構成は以下の通り。

接頭辞宣言

SELECT 変数1 変数2 ... 変数j
WHERE
{
  RDFトリプル文.
  ~中略~
  RDFトリプル文m.
}
結果修飾語句
  • 接頭辞宣言は「PREFIX 接頭辞 <述語が定義されているURI>」という書式で記載する。
  • 「WHERE{ }」の部分はWHERE節といい、WHERE節で列挙されているRDFトリプル文がすべて真となるような、変数割り当てが検索される。
  • WHERE節で割り当てられた変数のうち、SELECT句の横に列挙されている変数の順序組が出力として表示される
  • 結果修飾語句は、出力結果を制御する命令が列挙される。

_

オープンデータ時代の標準Web API SPARQLより。ja.dbpediaのSPARQLエンドポイントを開き、以下を入力する。

PREFIX dbpj: <http://ja.dbpedia.org/resource/>
PREFIX dbp-owl: <http://dbpedia.org/ontology/>

SELECT ?birth_date
WHERE
{
 dbpj:ビートたけし dbp-owl:birthDate ?birth_date.
}
  • 1行目:主語や目的語としてURIを入力する際の共通部分<http://ja.dbpedia.org/resource/>をdbpjとして定義している。
  • 2行目:今回利用する述語が定義されているURIをdbp-owlとして定義している。
  • 4行目移行:ビートたけしの生年月日を検索し、その結果を変数?birth_dateに格納して表示する。

応用例:dbp-owl:birthDateを述語として持つトリプルを検索し、主語を?actorに、目的語を?birth_dateに格納し、一覧表記する。

PREFIX dbpj: <http://ja.dbpedia.org/resource/>
PREFIX dbp-owl: <http://dbpedia.org/ontology/>

SELECT ?actor ?birth_date
WHERE
{
 ?actor dbp-owl:birthDate ?birth_date.
}
LIMIT 100

同一の主語の検索(セミコロン「;」の利用)_

WHERE句中で同一の主語で検索する場合はセミコロンを用いる。 以下の検索は同じ結果になる。

SELECT 変数A
WHERE
{
  変数A 述語A 目的語A.
  変数A 述語B 目的語B.
  変数A 述語C 目的語C.
}

セミコロンを用いる

SELECT 変数A
WHERE
{
  変数A 述語A 目的語A;
  述語B 目的語B;
  述語C 目的語C.
}

_

オープンデータ時代の標準Web API SPARQLより。

PREFIX dbpj: <http://ja.dbpedia.org/resource/>
PREFIX dbp-owl: <http://dbpedia.org/ontology/>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>

SELECT ?film_name
WHERE
{
 ?film dbp-owl:director dbpj:ビートたけし;
 dbp-owl:starring dbpj:ビートたけし;
 rdfs:label ?film_name.
}
LIMIT 100

値による絞り込み(Filter)_

SPARQL 1.1 Query Language「5.2.2 Scope of Filters」に使い方の例がある。

基本的には絞り込みをしたいものを変数に割り当て、FILTER式を使って絞り込む。

例:数字に対するフィルタリング_

オープンデータ時代の標準Web API SPARQLより。上演時間が100分未満のみを出力する。

PREFIX dbpj: <http://ja.dbpedia.org/resource/>
PREFIX dbpj-prop: <http://ja.dbpedia.org/property/>
PREFIX dbp-owl: <http://dbpedia.org/ontology/>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>

SELECT ?film_name ?screen_time
WHERE
{
 ?film dbp-owl:director dbpj:ビートたけし;
 dbpj-prop:上映時間 ?screen_time;
 rdfs:label ?film_name.
 FILTER (?screen_time < 100)
}
LIMIT 100

例:文字列に対するフィルタリング(REGEX, CONTAINS)_

オープンデータ時代の標準Web API SPARQLを参考。REGEXを用いて、ラベルに"ビート"から始まるラベルのものを列挙する。

PREFIX dbpj: <http://ja.dbpedia.org/resource/>
PREFIX dbpj-prop: <http://ja.dbpedia.org/property/>
PREFIX dbp-owl: <http://dbpedia.org/ontology/>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>

SELECT ?a ?label
WHERE
{
 ?a rdfs:label ?label.
 FILTER REGEX (?label, "^ビート")
}
LIMIT 100

CONTAINSは指定した文字列を含むかどうかで絞り込む。

PREFIX dbpj: <http://ja.dbpedia.org/resource/>
PREFIX dbpj-prop: <http://ja.dbpedia.org/property/>
PREFIX dbp-owl: <http://dbpedia.org/ontology/>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>

SELECT ?a ?label
WHERE
{
 ?a rdfs:label ?label.
 FILTER CONTAINS (?label, "ビート")
}
LIMIT 100

例:論理演算子の利用_

オープンデータ時代の標準Web API SPARQLより。

PREFIX dbpj: <http://ja.dbpedia.org/resource/>
PREFIX dbp-owl: <http://dbpedia.org/ontology/>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>

SELECT ?film_name ?director
WHERE
{
 ?film dbp-owl:director ?director;
 rdfs:label ?film_name.
 FILTER (?director = dbpj:ビートたけし || ?director = dbpj:北野武)
}
LIMIT 100

例:FILTER+IN_

オープンデータ時代の標準Web API SPARQLより。一つ前の例と同じ結果になる。

PREFIX dbpj: <http://ja.dbpedia.org/resource/>
PREFIX dbp-owl: <http://dbpedia.org/ontology/>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>

SELECT ?film_name ?director
WHERE
{
 ?film dbp-owl:director ?director;
 rdfs:label ?film_name.
 FILTER (?director IN(dbpj:ビートたけし, dbpj:北野武))
}
LIMIT 100

必須ではないパターンの指定(Optional)_

通常は、WHERE節で列挙されているRDFトリプル文がすべて真となるように変数の割り当てがされるが、検索条件として必須でないトリプル文を入れたい場合もある。その時にはOptional句を用いる。

_

以下はWikidataでの例。Wikidataエンドポイントに以下を入力して確かめると、Wikidataに登録されている日本のクラフトビールメーカーおよびビール識別子の一覧が表示される。ビール識別子に関してはこちらを参照のこと。

SELECT ?item ?itemLabel ?rate ?untap ?adv {
  ?item wdt:P31 wd:Q131734.
  ?item wdt:P17 wd:Q17 .
  OPTIONAL{?item wdt:P2905 ?r}.
  OPTIONAL{?item wdt:P3002 ?u}.
  OPTIONAL{?item wdt:P2904 ?a}.
  OPTIONAL{wd:P2905 wdt:P1630 ?format1} .
  OPTIONAL{wd:P3002 wdt:P1630 ?format2} .
  OPTIONAL{wd:P2904 wdt:P1630 ?format3} .
  BIND(IRI(REPLACE(?r, '^(.+)$', ?format1)) AS ?rate).
  BIND(IRI(REPLACE(?u, '^(.+)$', ?format2)) AS ?untap).
  BIND(IRI(REPLACE(?a, '^(.+)$', ?format3)) AS ?adv).
  SERVICE wikibase:label { bd:serviceParam wikibase:language "ja,en". }
}

Wikidataは登録されている項目に独自IDが割り振られている(wd:Qxxxという部分)。また、同様に述語にも独自IDが割り振られている(wdt:Pxxxという部分)。

WHERE節の3行目から8行目までにOPTIONAL句が使われている。各行の意味は以下の通り。

  • 1行目: 述語として「wdt:P31(分類)」 、目的語として「wd:Q131734(ブルワリー)」を持つトリプルを探し、その主語を?itemに割り当てる
  • 2行目: 述語として「wdt:P17(国)」 、目的語として「wd:Q17(日本)」を持つトリプルを探し、その主語を?itemに割り当てる
  • 3行目~5行目:述語「wdt:P2905(RateBeer brewery ID)」「wdt:P3002(Untappd brewery ID)」「wdt:P2904(Beer Advocate brewery ID)」をそれぞれ持っているトリプルがあれば、主語を?item、目的語を?r, ?u, ?a にそれぞれ割り当てる。トリプルがなければ無視する(OPTIONAL句)
  • 6行目~9行目:主語がそれぞれ「wd:P2905(RateBeer brewery ID)」「wd:P3002(Untappd brewery ID)」「wd:P2904(Beer Advocate brewery ID)」であり、述語「wdt:P1630(書式URL)」であるトリプルがあれば、目的語をそれぞれ?format1, ?format2, ?format3に格納する。トリプルがなければ無視する(OPTIONAL句)。なお、Wikidataでは各述語にも属性が割り振られている(例:RateBeer brewery ID
  • 10~12行目:取得した各識別子(RateBeer brewery ID、Untappd brewery ID、Beer Advocate brewery ID)の書式URL(正規表現となっている)を用いて、URLから識別子を抜き出し、それぞれ?rate, ?untap, ?advに格納している。
  • 13行目:Wikidata用の拡張書式。表示言語を指定している。

検索結果の結合(Union)_

2つの検索結果を結合するときにはUnionを使う。

例:二つの検索で同じ変数を用いる場合_

オープンデータ時代の標準Web API SPARQLより。以下の例では監督がビートたけしの映画と監督が北野武の映画の二つの検索結果を結合している。

PREFIX dbpj: <http://ja.dbpedia.org/resource/>
PREFIX dbp-owl: <http://dbpedia.org/ontology/>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>

SELECT ?film_name ?director
WHERE
{
 {
 ?film dbp-owl:director ?director.
 FILTER (?director = dbpj:ビートたけし)
 }
 UNION
 {
 ?film dbp-owl:director ?director.
 FILTER (?director =  dbpj:北野武)
 }
 ?film rdfs:label ?film_name.
}
LIMIT 100

例:二つの検索で異なる変数を用いる場合_

オープンデータ時代の標準Web API SPARQLより。UNIONが2つの検索結果をただ結合していることがわかる例。

PREFIX dbpj: <http://ja.dbpedia.org/resource/>
PREFIX dbp-owl: <http://dbpedia.org/ontology/>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>

SELECT ?film_name ?director_beat ?director_kitano
WHERE
{
 {
 ?film dbp-owl:director ?director_beat.
 FILTER (?director_beat = dbpj:ビートたけし)
 }
 UNION
 {
 ?film dbp-owl:director ?director_kitano.
 FILTER (?director_kitano =  dbpj:北野武)
 }
 ?film rdfs:label ?film_name.
}
LIMIT 100

検索結果の操作_

  • 「ORDER BY 変数」: 結果修飾語句として用いる。指定した変数の値に応じて整列させる。昇順(値が大きくなっていく)
  • 「ORDER BY DESC 変数」:結果修飾語句として用いる。指定した変数の値に応じて整列させる。降順(値が小さくなっていく)
  • 「LIMIT 数字」:結果修飾語句として用いる。検索結果の数を制限する。多くのエンドポイントでSPARQLの実行時間(X秒以上処理に時間がかかるSPARQL文は実行中止にする)には制限がかけられていることが多いので、LIMIT句をつけることが推奨されている。
  • 「OFFSET 数字」:結果修飾語句として用いる。検索結果の何番目から表示するかを指定する。「OFFSET 5」で検索結果の6番目以降から表示される。
  • 「DISTINCT」:SELECT文の後ろに置く(「SELECT DISTINCT 変数...」と記述する)。検索結果から重複している結果を取り除く

リンク_

戻る_