※ この記事は 『SPARQL Advent Calendar 2015』19日目のために書いた記事です。
最初に予防線を貼っておきますと、 本記事はSPARQLの効果的な使い方を広めるための記事ではありません。 あくまでもウェブサイトを運営する過程でたまたまSPARQLを使ってみたら便利だったよという経験談です。
背景:ビブリオバトル戦歴について
本ウェブサイト「状況に埋め込まれたブログ」(Jekyll製)では、 「ビブリオバトル戦歴」というページを設置しています。 ビブリオバトルとは書評ゲームの一種であり、 プレイヤーがそれぞれ面白いと思った本を持ち寄り、 1人5分間のプレゼンと2〜3分の質問をしたうえで、 観客と発表者を合わせた参加者全員の投票に寄って最も面白いと思った本=チャンプ本を決定するというものです。
ビブリオバトラー(ビブリオバトルに熱狂するプレイヤー)たちは日夜ビブリオバトルに参加しては、 めいめいビブリオバトルの参加記録を管理してはほくそ笑むという習性を持っているはずですが、 かくいう私もビブリオバトルをはじめた頃から今までの参加記録=戦歴を記録したいと思うようになり、 作成・公開したウェブページが「ビブリオバトル戦歴」なわけです。
問題:複雑な戦歴情報の管理とウェブページ作成をどう両立させるか
ページの内容をざっと見ていただければわかりますが、 1人のプレイヤーが参加するビブリオバトルのイベントはたいてい同じ主催者が企画しているものが多く、 またときには異なるイベントで同じ本を何度もプレゼンすることもあります。 そのため、 参加記録には同じ主催者や本が何度も登場するようになります。
最初はHTMLを直接編集して作成していた戦歴も、 件数が多くなるにつれてソースコードが分かりづらくなり、 主催者名や本のタイトルの統一が徐々に取れなくなるなど、 内容の整合性が取りづらくなってきました。 また、HTMLのままだと純粋にデータ管理上問題があり、 やがてビブリオバトル戦歴データそのものとウェブサイト上で公開するデザインを分離したいと思うようにもなりました。
これではいけないと、 ビブリオバトル戦歴データをYAMLファイルとして作り直し、 YAMLファイルから予め用意したテンプレートに沿ってウェブページを生成するように仕様変更しました。 しかし先に書いたような情報の統制の問題はこれでも解決せず、 悩んでいたわけです。
解決策: RDF+SPARQLでビブリオバトル戦歴ページを生成する
そこで採用に至ったのが、 RDFとSPARQLなわけです。 われながら前置きが長いですね…………
まず、ビブリオバトル戦歴データを以下のようなTurtleとして書き直しました。
@base <http://www.kunimiya.info/bibliobattle/> .
@prefix dcterms: <http://purl.org/dc/terms/> .
@prefix cc: <http://creativecommons.org/ns#> .
@prefix foaf: <http://xmlns.com/foaf/0.1/> .
@prefix schema: <http://schema.org/> .
@prefix biblio: <http://bibliobattle-records/terms/> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
# プレイヤーの情報
<#tsunekawa>
a schema:Person ;
schema:name "常川真央"@ja, "Mao Tsunekawa"@en ;
schema:homepage <http://www.kunimiya.info/> .
# ビブリオバトルでの発表情報
<#presen2015-11-22>
a biblio:Presentation ;
biblio:presenter <#tsunekawa> ; # 発表者
biblio:event <#event2015-11-22> ; # 参加したイベント
biblio:book <#book_identity> ; # 紹介した本
biblio:champion true . # チャンプ本を獲得したか否か
# ビブリオバトルのイベント情報
<#event2015-11-22>
a schema:Event ;
schema:date "2015-11-21"^^xsd:date ; # 開催日
schema:name "BiblioEi8ht チャンプカーニバル 2015 at クリエイトホール vol.5" ; # イベント名
schema:organizer <#biblioei8ht> ; # 主催者情報
schema:homepage <https://biblioei8ht.wordpress.com/2015/10/09/%E3%80%90%E9%96%8B%E5%82%AC%E6%83%85%E5%A0%B1%E3%80%91biblioei8ht-%E3%83%81%E3%83%A3%E3%83%B3%E3%83%97%E3%82%AB%E3%83%BC%E3%83%8B%E3%83%90%E3%83%AB-2015-at-%E3%82%AF%E3%83%AA%E3%82%A8%E3%82%A4/> . # イベントの詳細情報のURL
# 主催者の情報
<#biblioei8ht>
a schema:Organization ;
schema:name "BiblioEi8ht" ;
schema:homepage <https://biblioei8ht.wordpress.com/> .
# ビブリオバトルで紹介した本の情報
<#book_identity>
a schema:Book ;
schema:title "アイデンティティと暴力" ; # 本のタイトル
biblio:asin "4326154160" . # 本のASIN
そして、 Jekyllでウェブサイト構築時に、 独自に開発したプラグインを用いてビブリオバトル戦歴ページを生成します。
基本的な流れとしてはTurtleファイルを読み込み、 RDFリポジトリを一時的に構築します。 そして、 以下の様なSPARQLクエリで問い合わせを行います。
PREFIX profile: <http://www.kunimiya.info/profile/bibliobattle/#>
PREFIX schema: <http://schema.org/>
PREFIX biblio: <http://bibliobattle-records/terms/>
SELECT ?event_name ?event_date ?event_url ?organizer_name ?organizer_url ?book_title ?asin ?champion
WHERE {
?presen a biblio:Presentation .
OPTIONAL {
?presen biblio:event ?event
OPTIONAL { ?event schema:name ?event_name }
OPTIONAL { ?event schema:date ?event_date }
OPTIONAL { ?event schema:homepage ?event_url }
OPTIONAL {
?event schema:organizer ?organizer .
OPTIONAL { ?organizer schema:name ?organizer_name }
OPTIONAL { ?organizer schema:homepage ?organizer_url }
}
}
OPTIONAL {
?presen biblio:book ?book .
OPTIONAL { ?book schema:title ?book_title }
OPTIONAL { ?book biblio:asin ?asin }
}
OPTIONAL { ?presen biblio:champion ?champion }
}
ORDER BY DESC(?event_date)
すると、 以下のようなデータを抽出できます。
項目名 | 抽出結果 |
---|---|
event_name | BiblioEi8ht チャンプカーニバル 2015 at クリエイトホール vol.5 |
event_date | 2015-11-21 |
event_url | https://biblioei8ht.wordpress.com/2015/10/09/%E3%80%90%E9%96%8B%E5%82%AC%E6%83%85%E5%A0%B1%E3%80%91biblioei8ht-%E3%83%81%E3%83%A3%E3%83%B3%E3%83%97%E3%82%AB%E3%83%BC%E3%83%8B%E3%83%90%E3%83%AB-2015-at-%E3%82%AF%E3%83%AA%E3%82%A8%E3%82%A4/ |
organizer_name | BiblioEi8ht |
organizer_url | https://biblioei8ht.wordpress.com/ |
book_title | アイデンティティと暴力 |
asin | 4326154160 |
champion | true |
あとはあらかじめLiquidで書いておいたHTMLテンプレートにデータを流し込んでビブリオバトル戦歴を作成します。 (実際のテンプレートはこちらを、ウェブページを生成するスクリプトはこちらをご参照ください)
SPARQLを使ってみた感想
以上が現在のビブリオバトル戦歴ページの作成方法なのですが、 結果として戦歴のデータ管理とウェブページの生成が非常に楽に両立できるようになりました。
SPARQLを勉強した当初は、 DBPediaなど大規模なデータセットを扱うのになれておらず、 語彙を憶えるのが大変だったので、SPARQLの良さをなかなか体感することができませんでした。
しかし、 今回小規模に作成したLinked DataにたいしてSPARQLを活用してみて、 その柔軟な言語仕様がわずかながら分かるようになりました。
Linked Data技術は大変大きな可能性を秘めていますが、 人間の側はその可能性を引き出すように実践するのにまだ慣れていません。
今回のように小規模なユースケースが増えていくことで、 もしかしたらSPARQLのユーザが増えていくかもしれませんね。