SPARQL で LinkedData を取得・活用しよう！

#はじめに
ラクスアドベントカレンダー16日目の担当は[MasaKu](https://qiita.com/MasaKu)です！

さて、今回の記事ですが、とある勉強会でオープンデータについて発表させていただくかも知れないので、この機会にしっかりと勉強しなければと思い、以下の書籍を中心に勉強しました。

[オープンデータ時代の標準Web API　SPARQL](https://www.amazon.co.jp/dp/B017LQG9XC/ref=dp-kindle-redirect?_encoding=UTF8&btkr=1)

今回はオープンデータとLinkedDataを利用するための技術の一つであるSPARQLについて書きたいと思います。

#オープンデータとは
国や地方公共団体や事業者が保有するデータを以下の定義で誰もがインターネット上で利用できるようにしたものです。

>1. 営利目的、非営利目的を問わず二次利用可能なルールが適用されたもの
>2. 機械判読に適したもの
>3. 無償で利用できるもの
>
>[総務省｜ICT利活用の促進](http://www.soumu.go.jp/menu_seisaku/ictseisaku/ictriyou/opendata/index.html)

要するに、[クリエイティブ・コモンズ・ライセンスのCC0](https://creativecommons.jp/sciencecommons/aboutcc0/)に該当するデータがオープンデータになります。

[DATA.GO.JP](http://www.data.go.jp/data/dataset)という政府が管理しているサイトでは、データをカタログ化して公開されており、PDFやCSVなどの形式で公開されています。

#利用しやすいオープンデータ
とはいえ、単純にデータがインターネット上に公開されているだけでは、システムとして利用しやすいデータ形式とは言いにくいでしょう。

例えば、紙資料のスキャンデータをPDF形式で公開しているデータも、立派なオープンデータです。
しかし、システムと連携してデータを取得したりするには、高度な画像処理技術が必要になり、誰しもが扱いやすいデータ形式とは言えないのではないでしょうか。

Webの発明者であるティム・バーナーズ＝リーは、オープンデータのための5つ星スキームを提案しています

>★1 (どんな形式でも良いので) あなたのデータをオープンライセンスでWeb上に公開しましょう
>★2 データを構造化データとして公開しましょう (例: 表のスキャン画像よりもExcel)
>★3 非独占の形式を使いましょう (例: ExcelよりもCSV)
>★4 物事を示すのにURIを使いましょう，そうすることで他の人々があなたのデータにリンクすることができます
>★5 あなたのデータのコンテキストを提供するために他のデータへリンクしましょう
>
>[5つ星オープンデータ](https://5stardata.info/ja/)

上記のスキームからもわかりますが、誰もが自由に使えるライセンスでWeb上に公開することも立派なオープンデータとなります。
しかし、オープンデータとしてデータを成長させていくには、「汎用的に利用可能な形式で、その他のデータとも連携できるようにする」を目指してデータを公開していくことが求められます。

#LinkedDataについて
それでは、5つ星オープンデータのスキームの中で★5相当のデータであるLinkedDataについて見ていきたいと思います。

LinkedDataは、RDF(Resource Description Framework)という統一のグラフデータモデルを利用して公開されているという特徴があります。

RDFの最も基本的な形式は「主語」「述語」「目的語」の形式で記載されたデータを定義することです。（なお、この形式を「トリプル」といいます）

例えば、「ラクス」という主語に対して「従業員数」という述語に「659」という目的語を設定すると以下のような形式になります。

![1.PNG](https://qiita-image-store.s3.amazonaws.com/0/214717/ad553a95-5b4d-075a-5204-8b7bcb096c4a.png)

そして、これをRDFで表現すると以下のようになります。

```
@prefix sample: <http://sample.org/resource/>.
@prefix sample-prop: <http://sample.org/property/>.

sample:ラクス sample-prop:従業員数 sample:659;
```

上記のように、キーワード対してプロパティを設定してデータを定義することができます。

ほかにも「ラクス」というキーワードに「拠点」というプロパティを設定すると「東京」「大阪」「名古屋」「福岡」という値が設定できます。
そして、新たに設定された「東京」というキーワードにも「人口」というプロパティを設定して、値を設定することもできます。

![3.PNG](https://qiita-image-store.s3.amazonaws.com/0/214717/174f180c-fb83-dcbd-9366-6441ee3ddb0d.png)

このようにデータを連結していくことで、特的のキーワードを起点としてどんどんほかのデータにつなげていくことができます。

上記のようにRDFで定義されたデータに対してSPARQLを用いて「ラクスの拠点は？」という問い合わせを行うことで、該当するデータを取得できるようになります。

ずいぶん前置きが長くなりましたが、RDF形式のデータから特定の値を取得する方法がSPARQLというクエリ言語なのです。

#SPARQLの基本
とにもかくにも、まずはクエリそのものを見ていきたいと思います。
今回は、日本語のWikipediaに掲載されているデータをRDFで定義して公開している「[DBpedia Japanese](http://ja.dbpedia.org/sparql)」というRDBストアのSPARQLエンドポイントを利用したいと思います。

SPARQLのサンプルコードから実際にリソースを検索することができますので、直接実行してみるとわかりやすいかと思います。

以下のクエリは、DBpedia Japaneseから日本の国歌を取得するクエリです。

```日本の国歌検索
PREFIX dbp:<http://ja.dbpedia.org/resource/>
PREFIX dbp-prop:<http://ja.dbpedia.org/property/> 

SELECT ?o
WHERE{
  dbp:日本 dbp-prop:国歌 ?o.
}
```

お気づきの方もいらっしゃるかと思いますが、SPARQLによる問い合わせはSQL構文ともよく似ています。
そのため、SQLが理解できる方であればわかりやすいクエリ言語かと思います。

上記のクエリはWHERE条件に設定された`dbp:日本 dbp-prop:国歌 ?o.`という部分が重要です。
このクエリをRDFの「主語」「述語」「目的語」に分解すると、「主語」が`dbp:日本` 「述語」が`dbp-prop:国歌` 「目的語」が`?o`となります。

今回のクエリでは目的語の箇所が検索対象となったため`?o`を指定しました。
キーワードの頭文字に?もしくは$を記載すると、変数と認識され、検索条件に該当する値がセットされます。
これによって、「日本」の「国歌」に該当するデータが`?o`に格納され、SELECT句に記載された`?o`の箇所でデータを出力することができます。

なお、クエリの前半に記載された`PREFIX ~~~~`という部分はURIの省略記号の宣言です。
例えば、`dbp:日本`と記載された箇所は実際には`http://ja.dbpedia.org/resource/日本`となっています。

PREFIXによる省略記号を用いたほうが、クエリがシンプルになるだけでなく、対象のキーワードが指しているものが想像しやすくなっていると思います。

#様々な例題
引き続き、[DBpedia Japanese](http://ja.dbpedia.org/sparql)を用いて様々なパターンでデータを取得してみたいと思います。

##例題１
###ドラえもんの作者の代表作をすべて取得

```
PREFIX dbp-ja:<http://ja.dbpedia.org/resource/> 
PREFIX dbp-ja-prop:<http://ja.dbpedia.org/property/> 

SELECT ?author, ?masterpiece
WHERE{
  dbp-ja:ドラえもん dbp-ja-prop:作者 ?author.
  ?author dbp-ja-prop:代表作 ?masterpiece.
}
```

###解説
先ほど紹介した、「日本の国歌」を取得するSPARQLを少し応用した形です。
まず、WHERE句の`dbp:ドラえもん dbp-prop:作者 ?author.`の箇所でドラえもんの作者をデータを変数に格納します。

そしてその変数を用いて`?author dbp-prop:代表作 ?masterpiece.`を実行することにより、代表作の一覧を取得することができます。

日本人であれば、ドラえもんの作者が誰なのか、ということは想像しやすいでしょう。
しかし、作者がわからないような対象の場合は、まず作者を検索して、その検索結果から目的のクエリを発行する、というようなシーンで利用できそうです。

##例題２
###アメリカ合衆国というキーワードに関連するWikipediaの関連リンクを10件取得
```
PREFIX dbp-ja:<http://ja.dbpedia.org/resource/>
PREFIX dbp-owl:<http://dbpedia.org/ontology/>

SELECT ?wikiLink
WHERE{
  dbp-ja:アメリカ合衆国 dbp-owl:wikiPageWikiLink ?wikiLink.
}
LIMIT 10
```

###解説
SQLでも利用可能なLIMIT句がSPARQLでも利用可能です。
ここで注目していただきたいのは、「目的語」の箇所で記述している`dbp-owl:wikiPageWikiLink`という箇所です。

`wikiPagewikiLink`とは、その名のとおり、対象キーワードに関連するwikiページを定義するオントロジーです。
[DBpedia Japanese](http://ja.dbpedia.org/sparql)で「アメリカ合衆国」を検索すると、かなりの数の関連リンクが存在します。

大量の検索結果のうち、特定の件数だけを表示したい場合は`LIMIT`を利用します。
なお、SQL同様、`OFFSET`を利用することで指定した件数だけ飛ばしてデータを取得することもできます。

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

SELECT ?wikiLink
WHERE{
  dbp-ja:アメリカ合衆国 dbp-owl:wikiPageWikiLink ?wikiLink.
}
LIMIT 10 OFFSET 10
```

[定義元](http://dbpedia.org/ontology/)にアクセスすると、ほかにどのようなオントロジーが定義されているのかを確認することができます。

##例題3
###作成した作品数が多い順に監督名と作品数を表示
```
PREFIX dbp-owl:<http://dbpedia.org/ontology/>

SELECT ?director, COUNT(?director) AS ?count
WHERE{
  ?film dbp-owl:director ?director
}
GROUP BY ?director
ORDER BY DESC (?count)
```
###解説
こちらも、SQLでも利用可能な`GROUP BY`, `COUNT`, `ORDER BY`がSPAEQLで利用可能です。
先ほど同様にDBpedia Japaneseから`http://dbpedia.org/ontology/`で`director`と定義されているデータを取得します。

その後、監督を`GROUP BY`で集約した後、集約された件数を取得するため`COUNT`を実行します。
件数は`ORDER BY`で並べ替えもできます。

SQLと違って`ORDER BY`で降順を設定する際の記載が少し違うところがポイントです。

※`http://dbpedia.org/ontology/`には`MusicDirector`や`TheatreDirector`などのオントロジーも存在しますが、DBpedia Japaneseでは定義されていないようです。
厳密に定義できるようになれば、より正確な情報を取得することができるようになるでしょう。

#おわりに
今回はDBpedia Japaneseを利用してSPARQLの実行方法について簡単にご説明しました。

ブラウザ上からSPARQLの実行結果を取得する場合、HTMLとして結果を取得するとクエリの実行結果が確認しやすいですが、SPARQLエンドポイントは基本的にWebAPIからアクセスされることを前提としているようです。
そのため、クエリの実行結果はXMLやJSON形式で取得することもできます。

![4.png](https://qiita-image-store.s3.amazonaws.com/0/214717/1b9b0ebb-a9da-efe1-d6f0-918d90e282ab.png)

URIにGETリクエストを送るだけでデータを取得することができるため、SPARQLの実行結果をJSONでデータを受け取り、ブラウザ側で処理する、なんてこともできるようです。

RDFストアを拡充して行くとともに、オープンデータを利用したWebアプリ開発が盛んになればもっと面白そうなことができるんじゃないかと少しワクワクしました。

以上です！
明日の投稿は、[Misato Kii](https://qiita.com/kiimisato)さんです。
お楽しみに！