SPARQL Advent Calendar 2015、21日の記事です。1日くらい送れてしまいましたが...
Wikidata Query Service (Beta) に SPARQL 問合せを行ってみました。
Wikidata とは
Wikidata は、Wikimedia のプロジェクトの1つで、コミュニティによるデータの Wikipedia と言ったところでしょうか。データは三つ組で記述され、Linked Dataとして、他のサービスのURIにリンクさせることができます。最近SPARQLエンドポイントが公開されたそうです。
DBpedia が Wikipedia から機械的に抽出され作られたRDFデータであるのに対し、
Wikidata はコミュニティによって記述されたLinke Dataであるところが異なると認識しています。
(おかしな解釈だったらコメント下さい )
Wikidata Query Service に SPARQL エンドポイントが公開されています。
画面右上にある「Examples」から、数多くのサンプルを試すことができました。
SPARQL
Examples などを参考に、今回書いてみたクエリが以下です。
PREFIX wd: <http://www.wikidata.org/entity/>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX p: <http://www.wikidata.org/prop/>
PREFIX ps: <http://www.wikidata.org/prop/statement/>
select ?movie ?jalabel ?enlabel
where {
?movie p:P57 ?directorStatement . # director
?directorStatement ps:P57 wd:Q38222 .
?movie p:P179 ?seriesStatement . # series
?seriesStatement ps:P179 wd:Q462 .
?movie rdfs:label ?jalabel filter (lang(?jalabel) = "ja") .
?movie rdfs:label ?enlabel filter (lang(?enlabel) = "en") .
}
このクエリは、映画のID、日本語でのラベル、および英語でのラベルを得ます。映画の条件は
- series が Star Wars である
- director が George Lucas である
ような映画です。
つまり、「George Lucas が監督の、Star Wars シリーズの映画ID、日本語タイトル、および英語タイトル」を得るクエリです。
クエリ中の Predicate, Object はそれぞれ以下に対応しています。URIを見てだいたいどんなリソースかとわかると嬉しいですが、連番だと厳しいですね。
- P57: director
- P179: series
- Q38222: George Lucas
- Q462: Star Wars
以下が結果です。
?movie | ?jalabel | ?enlabel |
---|---|---|
wd:Q181069 | スター・ウォーズ エピソード2/クローンの攻撃 | Star Wars Episode II: Attack of the Clones |
wd:Q165713 | スター・ウォーズ エピソード1/ファントム・メナス | Star Wars Episode I: The Phantom Menace |
wd:Q17738 | スター・ウォーズ エピソード4/新たなる希望 | Star Wars Episode IV: A New Hope |
wd:Q42051 | スター・ウォーズ エピソード3/シスの復讐 | Star Wars Episode III: Revenge of the Sith |
細かいところだと直接 ?movie p:P57 wd:Q38222 .
と書きたいところですが、
property statement (ps:
) を経由しないとダメなようです。
そのため、?directorStatement
, ?seriesStatement
を経由して関係を記述しています。
(なぜこのような構造になっているか、どなたか教えていただけないでしょうか)
ちなみに、George Lucas でない監督の作品名と、その監督名は以下のクエリで得られます。
PREFIX wd: <http://www.wikidata.org/entity/>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX p: <http://www.wikidata.org/prop/>
PREFIX ps: <http://www.wikidata.org/prop/statement/>
select ?movie ?jalabel ?enlabel ?directorName
where {
?movie p:P57 ?directorStatement . # director
minus { ?directorStatement ps:P57 wd:Q38222 . } # not George Lucas
?directorStatement ps:P57 ?director .
?director rdfs:label ?directorName filter (lang(?directorName) = "en") .
?movie p:P179 ?seriesStatement . # series
?seriesStatement ps:P179 wd:Q462 .
?movie rdfs:label ?jalabel filter (lang(?jalabel) = "ja") .
?movie rdfs:label ?enlabel filter (lang(?enlabel) = "en") .
}
minus
は SPARQL 1.1 から入った機能のようです。この結果は以下になります。
?movie | ?jalabel | ?enlabel | ?directorName |
---|---|---|---|
wd:Q181803 | スター・ウォーズ エピソード6/ジェダイの帰還 | Star Wars Episode VI: Return of the Jedi | Richard Marquand |
wd:Q6074 | スター・ウォーズ エピソード7 | Star Wars: The Force Awakens | J. J. Abrams |
wd:Q181795 | スター・ウォーズ エピソード5/帝国の逆襲 | The Empire Strikes Back | Irvin Kershner |
エピソード7の邦題「フォースの覚醒」がついてないので、Wikipediaのように編集してみようと思います(-> 簡単に直せました)。
まとめというか感想
大学・大学院でLinked Data(RDF)の研究をしていたので、SPARQLを書くのは初めてではありませんでしたが、
卒業以来ほぼ2年ぶりくらいに書いたので、だいぶ時間がかかってしまいました。
Wikidata のエンドポイントは一般的な Virtuoso の SPARQL エンドポイントよりも使いやすかったです。
Wikidata は DBpedia と違って?(機械的に抽出していないという意味で)人がメンテナンスしているデータのように見えるので、
無駄に Predicate がたくさんくっついてるというような印象はありませんでした。