SPARQLで使うジャパンサーチ利活用スキーマ
SPARQLおさらい
- RDFグラフはトリプルの集合
- RDFは主語―述語―目的語の組(トリプル)で一つの情報を表現
- トリプルが集まったものをRDFグラフと呼ぶ
- グラフの中にはしばしば共通するパターンが含まれる
- SPARQLはグラフのパターンマッチで検索
- 人物と名前を変数とし、schema:nameを述語として持つトリプルパターン(
?who
schema:name?name
)を探す SELECT * WHERE {?who schema:name ?name}
- 人物と名前を変数とし、schema:nameを述語として持つトリプルパターン(
SPARQLの基本的な道具
- 検索条件(WHERE句内)
- 条件はトリプルパターンの組み合わせ(グラフパターン)で記述
FILTER
:値の絞り込み(グラフの完全一致を補完する)OPTIONAL
:アイテムによって有無が異なるパターン(画像など)→グラフパターンを{}
で囲む(グループグラフパターン)UNION
:グラフパターンの OR 検索(グループグラフパターンをUNION
でつなぐ)
- 結果の制御(WHRER句のあとに)
ORDER BY
:結果の並べ替え=ソートキーとする変数名を指定(デフォルトは昇順。DESC(?var)
とすると降順)LIMIT
:取得する検索結果の上限OFFSET
:LIMITと組み合わせ、結果のページングPREFIX schema: <http://schema.org> SELECT * WHERE { ?who schema:name ?name ; schema:email ?mail .
FILTER
(strends(str(?mail), "ndl.go.jp"))OPTIONAL
{?who schema:image ?image} }ORDER BY
?nameLIMIT
50
ジャパンサーチのSPARQLインターフェイス
- Snorql
- ブラウザで利用するときは、Snorqlインターフェイスが便利
https://jpsearch.go.jp
/rdf/sparql/easy/
- ジャパンサーチで用いる名前空間宣言をセット済み(省略記述できる)
- クエリ入力欄下、実行ボタンの右にクエリ例のメニューあり
- さらにその下のEasySPARQLを使うと、人、場所などからクエリ例を構築できる
- エンドポイント
- アプリケーション(ブラウザ内のJavaScript含む)から利用する場合は、末尾の
easy/
を除いた基本エンドポイントで https://jpsearch.go.jp
/rdf/sparql/
- Snorql画面で定義されている名前空間接頭辞は、PREFIXなしでも利用可能
- PREFIXをつけておくほうが、他のエンドポイントと組み合わせたりするときに混乱しないので、習慣としては吉
- アプリケーションからSnorqlのURLにEasySPARQLのクエリを投げることもできる
/api/easy-sparql/
に転送されて、ブラウザでの利用と同等のクエリに翻訳され、結果が得られる
- アプリケーション(ブラウザ内のJavaScript含む)から利用する場合は、末尾の
APIとしてのSPARQL
- クエリパラメータ(Virtuoso)
- query:URLエンコードしたSPARQLクエリ
- format:結果フォーマット(
json
|csv
|xml
)- TSVが欲しい場合は
text/tab-separated-values
- 略すと自動判定(acceptヘッダなしだとXML)
- TSVが欲しい場合は
- JSON結果フォーマット(標準仕様)
- クエリが成功すると、
results.bindings
内に結果セットの配列を持つJSONが返される - 配列各要素は、変数名をキーにしたオブジェクトで、各オブジェクトは
type
とvalue
を持つ {"results": { "
bindings
": [ { "who
": { "type": "uri", "value
": "http://example.org/#A" }, "name
": { "type": "literal", "value
": "John" } }, ... ] }}- 結果セット中(
OPTIONAL
の場合など)値がない変数は、そのキーが存在しない(空値ではない)
- クエリが成功すると、
ジャパンサーチ利活用スキーマ
- 「いつ」「どこ」「だれ」は二層構造で記述されている
- 1つの情報を、単純なSPO記述と、構造化ノードを介した記述に二重化している
- 単純記述と構造化記述の使い分け
- 「いつ」「どこ」「だれ」以外も含めすべてschema.orgを用いた基本記述で検索できる
- 「いつ」「どこ」「だれ」の値は正規化URIで記述される
- 構造化ノードは利活用スキーマ語彙(接頭辞
jps:
)で記述される - 構造化記述で役割、元データの記述値を確認できる。緯度経度などの細部情報も構造化記述に含まれる
ソースとアクセス
- 提供元データベースの情報
- ジャパンサーチへの提供元データに関する情報は
jps:sourceInfo
で構造化記述 schema:provider
:提供元データセット。あらかじめデータセットを絞り込むと効率的
- ジャパンサーチへの提供元データに関する情報は
- デジタル画像を含むアクセス情報
- アイテムへのアクセスに関する情報は
jps:accessInfo
で構造化記述 schema:associatedMedia
:アイテムのデジタル化データ(比較的高解像度の画像)schema:url
:アイテムに関する情報のURL(ウェブページの他IIIFマニフェストなど)schema:license
:デジタル化オブジェクトの利用ライセンス
- アイテムへのアクセスに関する情報は
画像などの提供者リソース
- サムネイル画像
- アイテムの
schema:image
の値として記述 - 提供される場合とされない場合があるので、
OPTIONAL
で取得するとよい ?s schema:creator chname:葛飾北斎 ; rdfs:label ?label .
OPTIONAL
{?sschema:image
?thumbnail}
- アイテムの
- 高解像度画像とIIIF
- IIIFマニフェストは文書なので、アクセス情報の
schema:url
で記述し、sc:Manifest
型を付与 ?s rdfs:label ?label ;
jps:accessInfo
/schema:url
?manifest . ?manifest a <http://iiif.io/api/presentation/2#Manifest
>- サムネイルとは別に高解像度画像が提供される場合は、アクセス情報の
schema:associatedMedia
で記述(例) ?s rdfs:label ?label ; schema:about chname:中村歌右衛門3代目 ;
jps:accessInfo
/schema:associatedMedia
?bigimage
- IIIFマニフェストは文書なので、アクセス情報の
文字列の扱い
- ジャパンサーチの基本的なリテラル値プロパティ
rdfs:label
:すべてのアイテムは必ず1つのラベルを持つ。結果表示に好適schema:name
:読みやサブタイトルも含めたアイテムの名前。ラベルの値も重複記述しているschema:description
:「いつ」「どこ」「だれ」で正規化されない大部分の値。元項目名を先頭に持つ場合がある。
- SPARQLでの文字列検索
- 値の完全一致以外は、FILTER句を使って絞り込み検索する
- 文字列の前方一致は
strstarts()
、後方一致はstrends()
、部分一致はcontains()
関数を使う ?s schema:name ?name ; schema:spatial place:京都 .
FILTER
(contains
(?name, "冷泉"))- ジャパンサーチ全体で部分一致検索を行なうと非常に重いので、複数のプロパティで絞り込むのが実用的
- ジャパンサーチがSPARQLエンドポイントに用いているVirtuosoは、独自のインデックスに基づくテキスト検索関数
bif:contains()
を提供する- 絞り込みなしでも実用的な検索ができる(ただし日本語検索は完全ではない)
?s ?p ?text . FILTER (
bif:contains
(?text, "'
山鉾巡行'
"))- ASCII以外の文字を検索するときは、引用符の中をさらに ' で囲む
- 述語を変数
?p
とすることで、全てのプロパティのリテラル値から「山鉾巡行」を検索できる(値によっては結果件数が爆発するので、LIMIT
を使う)
構造化記述の利用
- 構造化ノードの情報
jps:value
:ノードの正規化値。単純記述の目的語と一致jps:relationType
:親プロパティ(spatial、temporal、agential)を役割=働きの切り口で区分する。role:制作
、role:公開
、role:内容
など- 同じ人(例えば葛飾北斎)でも、作者の場合と、書物の主題の場合があり、agentialで一括検索を可能にしつつrelationTypeで区別する
schema:description
:主として元データの項目名+値。正規化前の値、表示名(俳号など)を確認できる- そのほか場所における緯度経度、出演者の役名など、基本パターンでカバーできない情報を追加できる
- 役者を検索する
- ARC浮世絵ポータルの役者絵で、「だれ」(
jps:agential
)の値は役者 - 構造化ノードの
schema:characterName
に役者が演じた配役を収めている - 弁慶を描いた作品を検索できる
SELECT * WHERE {?s jps:agential/
schema:characterName
chname:武蔵坊弁慶 }jps:agential/schema:characterName
という/
を用いた記述は後述のプロパティパス
- ARC浮世絵ポータルの役者絵で、「だれ」(
正規化とプロパティパス
- 作者、地名などの値は正規化URIで記述
- 北斎、葛飾卍老人、勝川春朗→いずれもchname:葛飾北斎
- Wikidata、DBpedia、Web NDLAなどと
owl:sameAs
で関連付け
- プロパティパスによる探索
- データセット自身が正規化URIをもつ場合はその値で記述される
- たとえば全国書誌の葛飾北斎はndla:00270331
- SPARQLのプロパティパスを用いて、両者を一括検索できる
- プロパティ(グラフの弧)を / で連結したパスで、ノード(節)間のサブグラフを示す
- パスを構成する弧は、反復演算子で出現数を指定できる(
?
なら0 もしくは1 回、*
なら0回以上、+
なら1回以上、など)
SELECT * WHERE { ?s jps:agential/jps:value/
owl:sameAs
*
chname:葛飾北斎 . }
タイプとファセット(集約)
- 基本区分としてのアイテム型
- ジャパンサーチのすべてのアイテムは(基本的に1つの)アイテム型(
rdf:type
)を持つrdf:type
はSPARQLではa
と省略記述できる
- アイテム型は階層化されているので、プロパティパスを用いて上位クラスに含まれるアイテムを一括検索できる
SELECT * WHERE {?s a
/rdfs:subClassOf*
type:絵画
}- Virtuosoの(日本語を含むIRI処理の?)制約により、クラスをIRIではなくラベルで指定する方がよい場合があるので注意
- 絞り込みの他、予備知識のないデータセットの内容(形態)を大まかに把握する。
- ジャパンサーチのすべてのアイテムは(基本的に1つの)アイテム型(
- ファセットとしての集約
- SPARQLの集約句
GROUP BY
を用いて、データセット内のアイテムをタイプ別にグループ化 SELECT
?key
(count
(?s) as ?count) WHERE { ?s a?key
; jps:sourceInfo/schema:provider chname:ColBase }GROUP BY
?key
ORDER BY desc(?count)- 文字列検索と組み合わせ、あるキーワードを含むデータがどのデータセットにあるかを調べることもできる
SELECT ?key (count(?s) as ?count) WHERE { ?s jps:sourceInfo/schema:provider ?key ; ?p ?text FILTER
bif:contains
(?text, "'弁慶'") }GROUP BY
?key ORDER BY desc(?count)
- SPARQLの集約句
時間情報のモデルとクエリ
- 時間記述のモデル
- 時間情報はすべて年単位で正規化しURI付与
- 年範囲も
time:1801-1845
のような形で正規化URIで表現 - 単年もふくめ、これらのリソースは開始年、終了年を持つ。
time:1801-1845
jps:start
1801 ;jps:end
1845- 時代、正規も開始年、終了年を用いて定義される
time:室町時代 jps:start 1336 ; jps:end 1573
- 時間範囲の検索
- 時代が年範囲で定義されることを利用して、その範囲に含まれるアイテムを検索できる(※重いクエリ)
SELECT ?when (count(?s) as ?count) WHERE { ?s schema:temporal ?when . ?when jps:start
?sty
; jps:end?edy
. #室町時代の開始年、終了年定義を利用して絞り込む time:室町時代 jps:start?murost
; jps:end?muroed
. FILTER(?sty
>=?murost
&&?edy
<=?muroed
) } GROUP BY ?when ORDER BY ?when- 各年実体を時代実体とschema:isPartOfで関連付けたので、それを使うほうがずっと速く結果が得られる
SELECT ?when (count(?s) as ?count) WHERE { ?s schema:temporal ?when . { ?when
schema:isPartOf?
time:室町時代 } UNION { ?whenjps:startEntity
/schema:isPartOf
time:室町時代 . ?whenjps:endEntity
/schema:isPartOf
time:室町時代 . } } GROUP BY ?when ORDER BY ?when
場所情報のモデルとクエリ
- 場所情報のモデル
- 場所情報は都道府県(海外は国)単位で正規化
palce:京都
は場所リソースとしての京都(末尾に府/市を持たない)chname:京都府
は自治体としての京都府。
- 元データの住所表記などは構造化ノードの
schema:description
に - 市郡レベルのデータがある場合は、構造化ノードに
jps:region
で追記(例:京都市で撮影された写真) - アイテムが博物館などにある場合は、
jps:accessInfo/schema:itemLocation
に記述する(例:京都国立博物館所蔵の中国の書)- 所蔵館はアイテム固有の情報ではない(所蔵館が変わる場合もある)ため、spatialには記述しない
- 場所情報は都道府県(海外は国)単位で正規化
- 構造化ノードと緯度経度
- 緯度経度情報がある場合は、構造化ノードの
schema:geo
で記述する schema:geo
の値はgeohashのURIとなり、その値が緯度経度を持つ- geohashのURIは、緯度経度の他に
jps:within
で親ハッシュURIと関連付け jps:spatial [
jps:value
place:京都 ;schema:description
"所在地: 京都府京都市東山区清水一丁目" ;schema:geo
<http://geohash.org/xn0x1fdweh
> ] ... <http://geohash.org/xn0x1fdweh
>schema:latitude
34.99534 ;schema:longitude
135.7836 ; #7桁以上のgeohashはまず6桁のgeohashに関連付けているjps:within
<http://geohash.org/xn0x1f> .
- 緯度経度情報がある場合は、構造化ノードの
緯度経度と範囲検索
- Geohash
- geohashは上位桁が同じなら同じ領域に含まれる。桁数は粒度の目安=3桁なら都道府県、4桁なら市郡レベルなど
- 名所図会を利用する
- ジャパンサーチの平安京都名所図会アイテムは、
schema:about
の値として位置情報を持つ寺社などが登録されている jps:within
とプロパティパスを組み合わせると、一定範囲のアイテムをグラフ探索できるSELECT * WHERE{ ?s rdfs:label ?label ; jps:spatial/
schema:geo/jps:within
?where . #興正寺の位置情報から、範囲を取得する <https://jpsearch.go.jp/entity/chname/興正寺(円頓山)> schema:location/schema:geo/jps:within
?where }
- ジャパンサーチの平安京都名所図会アイテムは、
補足とまとめ
- もっと例を見るには
- ジャパンサーチSPARQLクエリ集 - 新データセット追加時にTwitterで紹介してきた特徴的なクエリ
- 非公式サポートページ - 上のクエリ集を含む応用事例集
- 補足とヒント
- クエリの設計はグラフをイメージしながらすすめるとよい。円と矢印の図を手書きしてみるのもおすすめ
- 基本モデルは共通だが、画像、IIIFマニフェストなどデータセットによって提供状況が異なる情報がある点に注意→
OPTIONAL
をうまく使う - 作者などの正規化URIが分からないときはジャパンサーチ名鑑(正規化名索引)が役に立つかも
- ライセンス:あるていどクエリが固まったら、ライセンスを念のために確認する(クエリ集に応用例あり)。
- クレジット:できるだけクレジットや来歴を示す。詳細画面でアイテムURIあるいはデータソース(
jps:sourceInfo/schema:provider
)を表示するなど
- そのほかの参考リソース
- ジャパンサーチSPARQエンドポイントの解説(公式サイト)
- 利活用スキーマの設計と応用(三田図書館情報学会月例会の講演スライド資料)
- Web NDLAのSPARQL API仕様書(SPARQL 1.1の説明。PDF)
- 楽しんでください!
参照先
- 参照したリソース
- Snorql for Japan Search
<https://jpsearch.go.jp/rdf/sparql/easy/> - schema.org
<http://schema.org> - ジャパンサーチ利活用スキーマ概説
<https://jpsearch.go.jp/api/introduction/> - Property Paths - SPARQL 1.1 Query Language §9, 2013-03-21, W3C Recommendation
<https://www.w3.org/TR/sparql11-query/#propertypaths> - Tips & Tricks - geohash.org
<http://geohash.org/site/tips.html> - ジャパンサーチSPARQLクエリ集
<https://www.kanzaki.com/works/ld/jpsearch/query-examples> - ジャパンサーチ“非公式”サポートページ
<https://www.kanzaki.com/works/ld/jpsearch/> - ジャパンサーチ名鑑
<https://www.kanzaki.com/works/ld/jpsearch/chname-index> - ジャパンサーチSPARQエンドポイントの解説
<https://jpsearch.go.jp/api/sparql-explain/> - ジャパンサーチ利活用スキーマの設計と応用, 2019-07-27
<https://www.kanzaki.com/works/2019/pub/0727mls.html> - Web NDLAのSPARQL API仕様書
<https://id.ndl.go.jp/information/wp-content/uploads/2018/05/api-spec.pdf>
- Snorql for Japan Search