【データの集め方講座】SPARQLの基本文法と実践方法
はじめに
ご高覧いただきありがとうございます.
ソフトウェアエンジニアのKitaharaです.
本日は葛飾北斎を題材にしながら「とりあえず基本的なことなら書ける」を
目標にSPARQLの基本文法を解説します!
SPARQLが初めてという方へ
SPARQLは便利ではあるのですが少しマイナーな言語です.
そこでSPARQLは何かやSQLとの違いをまとめた記事を作りました!
まずはこちらから見てみてください!
備考
本記事ではTurtle形式という形式で書いていきます.
あらかじめご了承ください.
SPARQL基本文法
基本中の基本
SPARQLの扱うデータは
主体--(関係性)-->対象
というトリプルという形式で, データ集合はそのトリプルデータが集まった集合です.
つまり, データが主体と対象が関係性によって結ばれた網目のような形になっています. (詳しくは下記の記事を見てください)
SPARQLではこのグラフデータをWHEREに記述することでデータ集合を確定させてそこから対象のデータFILTER等を用いて取得します.
詳しく見ていきましょう
SELECT *
WHERE { <http://ja.dbpedia.org/resource/東京都> ?p ?o . }
LIMIT 100
クエリを実行した結果です.
ここでは
<http://ja.dbpedia.org/resource/東京都> -- (?p) --> (?o)
という
主体--(関係性)-->対象
の関係が検索されていることが分かります.
SPARQLではトリプルに変数を入れることができます.
?を接頭辞にすると変数としてみなされます.
つまり, ?p, ?oは変数になります.
変数はその部分を表すものでありながら制限をしないときに使います.
先程のトリプルは
「http://ja.dbpedia.org/resource/東京都」と何でもよいので「関係性」をもつすべての「対象」を検索していたことがわかります.
実際に結果を見ると色々なデータが出てきたと思います.
省略記法
とはいえWHERE内にURIを書いていたのでは可読性が悪くなってしまいます.
SPARQLではこのような事態にならないように省略記法が存在しています.
URIの一部をあらかじめPREFIXで登録してWHERE内ではURIを省略して書という方法です. 具体的には以下の様に書きます.
PREFIX dbpj: <http://ja.dbpedia.org/resource/>
PREFIX dbp-owl: <http://dbpedia.org/ontology/>
SELECT ?birth_date
WHERE
{
dbpj:葛飾北斎 dbp-owl:birthDate ?birth_date.
}
ここでは以下の二つのURIを省略しています.
省略前
(1) http://ja.dbpedia.org/resource/葛飾北斎
(2) http://dbpedia.org/ontology/birthDate
省略後
(1)' dbpj:葛飾北斎
(2)' dbp-owl:birthDate
このように書くことで可読性を確保することができます.
トリプルの意味としては
「http://ja.dbpedia.org/resource/葛飾北斎」と「http://dbpedia.org/ontology/birthDate」の関係性を持つすべての「対象」
で?birth_dateを集めていることが分かります.
備考
ここで「データは集められることは分かった. でもどこからhttp://dbpedia.org/ontology/birthDateという語彙を見つけたんだろう」と考えられている方もいると思います.
その答えは以下のクエリで解決します.
PREFIX dbpj: <http://ja.dbpedia.org/resource/>
PREFIX dbp-owl: <http://dbpedia.org/ontology/>
SELECT ?p, ?o
WHERE
{
dbpj:葛飾北斎 ?p ?o .
}
私たちが気になっているデータは少なくとも葛飾北斎という単語です.
なので葛飾北斎という主体だけ固定して, 関係性を変数にすることで葛飾北斎という主体とつながりのある対象との関係性をすべて取得できます.
その中から探していけば目的の関係性を表す語が見つかると思います.
複数のパターン指定
さて葛飾北斎の作品を取得したいとしましょう.
主体は分かっているものの作品名と関係性が分かりません.
そこで以下のコードを書いて調べてみることにします
PREFIX dbpj: <http://ja.dbpedia.org/resource/>
PREFIX dbp-owl: <http://dbpedia.org/ontology/>
SELECT ?name, ?p
WHERE
{
?name ?p dbpj:葛飾北斎 .
}
すると以下のようなデータが出力されました.
http://ja.dbpedia.org/までは同じなのですが, その先が異なっている様です. 全部のデータが同じであれば問題ないのですが判別するのにも時間がかかります.
このような場合は複数の対象を指定することで解決します.
PREFIX dbpj: <http://ja.dbpedia.org/resource/>
PREFIX dbp-owl: <http://dbpedia.org/ontology/>
PREFIX dbp-prop: <http://ja.dbpedia.org/property/>
SELECT DISTINCT ?name
WHERE {
?name dbp-owl:creator dbpj:葛飾北斎;
dbp-owl:painter dbpj:葛飾北斎;
dbp-prop:artist dbpj:葛飾北斎.
}
値を選別する
今度は葛飾北斎の作品の発表年が気になってきたので調べてみます.
下記のコードを実行すると出版年を見ることができました.
PREFIX dbpj: <http://ja.dbpedia.org/resource/>
PREFIX dbp-owl: <http://dbpedia.org/ontology/>
PREFIX dbp-prop: <http://ja.dbpedia.org/property/>
SELECT ?p, ?o
WHERE {
dbpj:凱風快晴 ?p ?o
}
ではこの凱風快晴より発表年が前のものはどれぐらいあったのでしょうか?
値を絞るためにはFILTERを使います.
PREFIX dbpj: <http://ja.dbpedia.org/resource/>
PREFIX dbp-owl: <http://dbpedia.org/ontology/>
PREFIX dbp-prop: <http://ja.dbpedia.org/property/>
SELECT ?year, ?name
WHERE {
?name dbp-owl:creator dbpj:葛飾北斎;
dbp-owl:painter dbpj:葛飾北斎;
dbp-prop:artist dbpj:葛飾北斎.
?name dbp-prop:year ?year .
FILTER (?year > 1831)
}
実行されたのですがデータが出てきませんでした.
どういうことでしょうか?
調べてみます.
PREFIX dbpj: <http://ja.dbpedia.org/resource/>
PREFIX dbp-owl: <http://dbpedia.org/ontology/>
PREFIX dbp-prop: <http://ja.dbpedia.org/property/>
SELECT ?year, ?name
WHERE {
?name dbp-owl:creator dbpj:葛飾北斎;
dbp-owl:painter dbpj:葛飾北斎;
dbp-prop:artist dbpj:葛飾北斎.
?name dbp-prop:year ?year .
}
なんとすべて1831年で登録されていたようです.
念のため下記のコードで誕生年と没年を調べてみました
PREFIX dbpj: <http://ja.dbpedia.org/resource/>
PREFIX dbp-owl: <http://dbpedia.org/ontology/>
PREFIX dbp-prop: <http://ja.dbpedia.org/property/>
SELECT ?birthYear, ?deathYear
WHERE {
dbpj:葛飾北斎 dbp-owl:birthDate ?birthYear.
dbpj:葛飾北斎 dbp-owl:deathDate ?deathYear.
}
どちらも違うようです.
本当に1年の間に大作を6つも仕上げたのでしょうか…?
もしわかる方がいればコメント欄で教えてほしいです!
おわりに
今回はSPARQLの基本文法解説をしました!
参考になったという方はぜひハートボタンを押していってください!
モチベーションが上がります!
記事内で不明な点等ございましたら気軽にご連絡ください.
Twitter: @kitahara_dev
email: kitahara.main1@gmail.com