Wikidata Query Service に SPARQL 問合せをしてみた

[SPARQL Advent Calendar 2015](http://qiita.com/advent-calendar/2015/sparql)、21日の記事です。1日くらい送れてしまいましたが...

Wikidata Query Service (Beta) に SPARQL 問合せを行ってみました。

# Wikidata とは

[Wikidata](https://www.wikidata.org/) は、Wikimedia のプロジェクトの1つで、コミュニティによるデータの Wikipedia と言ったところでしょうか。データは三つ組で記述され、Linked Dataとして、他のサービスのURIにリンクさせることができます。最近SPARQLエンドポイントが公開されたそうです。

[DBpedia](http://wiki.dbpedia.org/) が Wikipedia から機械的に抽出され作られたRDFデータであるのに対し、
Wikidata はコミュニティによって記述されたLinke Dataであるところが異なると認識しています。
（おかしな解釈だったらコメント下さい :bow:）

[Wikidata Query Service](https://query.wikidata.org/) に SPARQL エンドポイントが公開されています。
画面右上にある「Examples」から、数多くのサンプルを試すことができました。

![スクリーンショット 2015-12-22 午前2.39.21.png](https://qiita-image-store.s3.amazonaws.com/0/1896/bde1db68-014c-1f33-950f-0a52e1a2ce83.png)

# SPARQL

Examples などを参考に、今回書いてみたクエリが以下です。

```sparql
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](https://www.wikidata.org/wiki/Property:P57)
- P179: [series](https://www.wikidata.org/wiki/Property:P179)
- Q38222: [George Lucas](https://www.wikidata.org/wiki/Q38222)
- Q462: [Star Wars](https://www.wikidata.org/wiki/Q462)

以下が結果です。

|?movie|?jalabel|?enlabel|
|:----:|:------:|:------:|
|[wd:Q181069](http://www.wikidata.org/entity/Q181069) | スター・ウォーズ エピソード2/クローンの攻撃 | Star Wars Episode II: Attack of the Clones|
|[wd:Q165713](http://www.wikidata.org/entity/Q165713) | スター・ウォーズ エピソード1/ファントム・メナス | Star Wars Episode I: The Phantom Menace|
|[wd:Q17738](http://www.wikidata.org/entity/Q17738) | スター・ウォーズ エピソード4/新たなる希望 | Star Wars Episode IV: A New Hope|
|[wd:Q42051](http://www.wikidata.org/entity/Q42051) | スター・ウォーズ エピソード3/シスの復讐 | Star Wars Episode III: Revenge of the Sith|

細かいところだと直接 `?movie p:P57 wd:Q38222 .` と書きたいところですが、
property statement (`ps:`) を経由しないとダメなようです。
そのため、`?directorStatement`, `?seriesStatement` を経由して関係を記述しています。
（なぜこのような構造になっているか、どなたか教えていただけないでしょうか）

ちなみに、George Lucas でない監督の作品名と、その監督名は以下のクエリで得られます。

```sparql
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](http://www.wikidata.org/entity/Q181803)|スター・ウォーズ エピソード6/ジェダイの帰還|Star Wars Episode VI: Return of the Jedi|Richard Marquand|
|[wd:Q6074](http://www.wikidata.org/entity/Q6074)|スター・ウォーズ エピソード7|Star Wars: The Force Awakens|J. J. Abrams|
|[wd:Q181795](http://www.wikidata.org/entity/Q181795)|スター・ウォーズ エピソード5/帝国の逆襲|The Empire Strikes Back|Irvin Kershner|

エピソード7の邦題「フォースの覚醒」がついてないので、Wikipediaのように編集してみようと思います（-> 簡単に直せました）。

# まとめというか感想

大学・大学院でLinked Data（RDF）の研究をしていたので、SPARQLを書くのは初めてではありませんでしたが、
卒業以来ほぼ2年ぶりくらいに書いたので、だいぶ時間がかかってしまいました。

Wikidata のエンドポイントは一般的な Virtuoso の SPARQL エンドポイントよりも使いやすかったです。

Wikidata は DBpedia と違って？（機械的に抽出していないという意味で）人がメンテナンスしているデータのように見えるので、
無駄に Predicate がたくさんくっついてるというような印象はありませんでした。

# 参考

- Fumi1先生のブログ記事
  - [Wikidata Linked Data](http://fumi.me/2014/04/03/wikidata-linked-data/)
  - [Wikidata Query Service](http://fumi.me/2015/12/09/wikidata-query-service/)
- [Erxleben, Fredo, et al. "Introducing Wikidata to the linked data web." The Semantic Web–ISWC 2014. Springer International Publishing, 2014. 50-65.](http://korrekt.org/papers/Wikidata-RDF-export-2014.pdf)
- [What is the difference between Wikidata and DBpedia?](https://www.quora.com/What-is-the-difference-between-Wikidata-and-DBpedia)
  - 長すぎて読んでないけど