はじめに

Odeuropaは、ヨーロッパの香りの歴史を研究するプロジェクトで、絵画、文学、その他の歴史的資料に描かれた香りの表現を収集・分析しています。本記事では、OdeuropaのSPARQLエンドポイントを活用し、SKOS(Simple Knowledge Organization System)語彙体系に基づいた香りデータの可視化Webアプリケーションの実装について紹介します。

https://odeuropa-seven.vercel.app/ja/

プロジェクト概要

技術スタック

  • フロントエンド : Next.js 15 (App Router)
  • UI : Material-UI v5
  • 国際化 : next-intl
  • データ取得 : SPARQLクエリ (Odeuropa SPARQLエンドポイント)
  • 言語 : TypeScript
  • ホスティング : 静的サイト生成(SSG)

主な機能

1. 香り検索 (/odeuropa-sources)

アプリケーションの中核となる機能で、Odeuropaプロジェクトが収集した香りの知覚イベント(smell perception events)を検索・閲覧できます。

主な特徴:

  • 複雑なSPARQLクエリによるデータ取得
    • 香り放出イベント(emission)、香りオブジェクト、ソース(絵画・文学作品など)、テキスト断片を結合
    • CRMベースのオントロジー(ecrm:P67_refers_to, od:F1_generatedなど)を活用
  • 多軸フィルタリング
    • SKOS語彙による香りの源でフィルタ(?xパラメータ)
    • ソースタイプフィルタ(視覚的アイテム E36_Visual_Item / 言語オブジェクト E33_Linguistic_Object
  • リッチな情報表示
    • 香りのラベル、ソース情報(タイトル、画像、URI)
    • テキスト断片の引用
    • 嗅覚体験の質的情報(Olfactory Experience)
  • ページネーション - 20件ずつの効率的な表示

SPARQLクエリ例:

SW}EHLEERCE??#{}}Tee{mmUDiiNIss???I?SssffsOsTiirroNoIooaauuNnnggr{rCmmccTooeeeeddnn??::tteeseFFccom31errrui__cdmmrshgrf::csaem:PPeidn:v16o_ePa67?nsr6l5_soa7u_ro?ut_eieusrernfrmcde?ceceefforel?errs_l?srap_txmsgoti?e_mrots.ltealmlont?eeteel.?_sm?levif_ma?srlilfsaasurigbseaomeignelo.mnne.t?ns.t?ofu.rracgem_einmta_gvealue

2. 香り詳細ページ (/odeuropa-sources/item)

個別の香りに関する詳細情報を表示するページです。

表示情報:

  • 基本情報
    • 香りのURI、ラベル
    • Wikidataへのリンク(owl:sameAs
    • 香りの源(smell source)
  • 関連するソース
    • 複数のソース(絵画、文学作品など)を一覧表示
    • 各ソースの画像、タイトル、URI
    • テキスト断片の引用
    • 嗅覚体験の詳細情報
  • メタデータ
    • 時間情報(time:hasTime
    • 著者、作成日、言語

実装のポイント:

cc`oo;nnSW}UssEHRttLEB#LERIsgCENmeTDet{(lS?<lms$Uem{rSleuiPllrADli=Re}UQt?>RsLasIeimAaleSrQlcul?he_sPrlmayaerbla=elml)s(.u?grseimt:e(l'slut_rrsiio'nu)gr;)ce=>?s`ource?source_title

3. コンセプト一覧 (/concepts)

SKOS Top Conceptsを一覧表示し、香りの語彙体系の全体像を把握できます。

主な特徴:

  • SKOS Top Conceptsのみを表示(skos:topConceptOf
  • 画像、代替ラベル、Wikidataリンクなどのメタデータ表示
  • 子コンセプト数の表示
  • 階層ツリーへの遷移ボタン
  • アルファベット順でのソート

4. 階層ツリー (/hierarchy)

香りの源の階層構造を対話的に探索できます。

主な特徴:

  • 動的な階層構造の可視化
  • 遅延読み込みによる効率的なデータ取得
  • ?top=URIパラメータによる柔軟なルート指定
  • レベル別の色分け
  • 各ノードから香り検索へのリンク

5. コレクション (/collections)

SKOS Collectionsを表示し、テーマ別にグループ化された香りの源を閲覧できます。

主な特徴:

  • SKOS Collectionsの一覧表示
  • メンバー数の表示
  • コレクションメンバーの検索

Odeuropaのデータ構造とSPARQL

データモデルの概要

Odeuropaプロジェクトは、CIDOC-CRM(Conceptual Reference Model)を拡張した独自のオントロジー(Odeuropa Data Model)を使用しています。主要なエンティティと関係性は以下の通りです:

1. 香りのイベントモデル

#?#?#?essmmmieesootlrolssssddilddlkkki::mf:SooooFFeashSosssn31::aKu:::__holsOrpbnahgada_ScrraSaesS:bseeormodnTmLemfared_eie1leaLdol:srml_laewlLoaelS?lsbre1utms_kerE1re?emsol?m_cdtleosb?iSeillu:?rnsm?mlrCpoase?se;LcorarilsmIaenedrolmenbcfeon_elte?eLrwEllelspaCemlrotboriS;v;uenCsoar;lcosulcenire;pcoc.tene.p;t;;.#####

2. ソースとテキスト断片の関係

#?#?sforuarrsegrecdccmdcefhrefrsemn:ma:m:tv:l:PaPeai1al6cbm6u7rea5ee_mlg_cr:eir?eE?nmff3s?c:re6osoEar_uor3gsVrup3m_icro_etsecrLnouTeaitaiItnV?ltmegae_lasulmIegiuite?sese;ftsm;ri;iaco;g_nmOeb.njtec.t;####E33_Linguistic_Object

3. 嗅覚体験(Olfactory Experience)

#?#?eqxupaeeelrcciirrtemmyn::cPPre11dA44fs01ss__:iaalgssanssbmiieegglnnntee"ddpa_la?eetqactusrraamiln:bitEut"1ty@3ee__.nAtto.tr?isbmuetlel_A;ssignment;

使用している主な語彙とプレフィックス

PPPPPPPPPRRRRRRRRREEEEEEEEEFFFFFFFFFIIIIIIIIIXXXXXXXXXsrreoostocddcldkiwhffrf:omles:m:se:m::<:::<<h<<h<ht<<h<hthtthhthttttptttttptp:ttptp:p:pp:p::::sd/:wdawwweatwww/wwrtawwwsw.la.ww.c.wa.o..whw3nodww3e3.gde33.m.oeeu..oaornuroor.rg-rorrgogcopggr1rpa2g29ma.220/09..e000>09eu0020ru460go/002n0t71cot2i/2uco/mor2ralsewd-rbok#lfreugo>#-dnlys>sfta//c-/r>chs>yoey/rmnoeatl##af>>xa-cntso#r>y-objects/>

主要な語彙の説明:

プレフィックス用途
od:Odeuropa独自のオントロジー(香り放出、香り生成など)
ecrm:CIDOC-CRM(文化遺産のメタデータ標準)
skos:SKOS(知識組織システム、香りの源の分類)
schem:Schema.org(画像、著者、日付などの基本メタデータ)
time:OWL-Time(時間情報)
owl:OWL(Wikidataなどへの同一性リンク)

SPARQLクエリの実装

1. 香り検索クエリの実装

香り検索機能では、複数のエンティティを横断する複雑なクエリを実行します。

基本的なクエリ構造

PPPSW}LORRREHIFEEELEMFFFFERISIIICE#?#?O}#{}}#O}TEXXXTeePPT{1m2mT3U4T2oesD.i.iI.N.I00dckIssO?#????I#??O?F:roSssNsffssOssNsImsTiiAmrrooNooAoL<::IooLeaauuuuLuThNnnlggrr{rrrEt<<C{lmmcccc{cRthhToo1eeee2eee(pttddr:nn:S:tt??::dtterersT/ppseFFf2cdcdcR/::om31serrfrfhSd/ui__:cdmsmseTa/rshglrf::::mAtewcsaeam:PlPl:Rarweidnb:v1a6aiT.lwo_eePa6b7bmSoa.?nsrl6l5e_ea(dnwsoa7u_lrlgSeg3o?ut?_eieeTue.usresrn?f?Rrnormcdme?cses?(o-rceeeffooros?pcgel?lerrusuosar/_l?slrapr_ruo.m2txm_sgoctcrue.0i?el_mreoecru0ts.latea__ecr4lmlbontt?t_eogeeeteieii_n0l.l?_stmtmitc2?levlilamou/f_.ma?esegalrsrlilfsegorkaasur.i.egeogbseao.)ynsmeign,/telo.m>cnne."ot?nhrs.tte?ot#fu.p>rrsac:ge/m_/eidnmatat_gave.aoldueeuropa.eu/image/"))

フィルタリングの実装

SKOS語彙によるフィルタ(?xパラメータ):

#{}}?U#FxNIILsOTkNEoRs{(:?bxro=ad<ehrt*tp<:h/t/tdpa:t/a/.doadteau.roodpeau.reoup/av.oecua/bvuolcaarbyu/loalrfya/cotlofrayc-toobrjye-cotbsj/e4c0t5s>/)405>

skos:broader* はプロパティパスで、階層的な関係を再帰的にたどります。これにより「食べ物(Food)」を指定すると、「パン」「肉」などの子孫概念も含めて検索できます。

ソースタイプによるフィルタ:

#?#?ssoouurrcceerrddff::ttyyppee<<hhttttpp::////eerrllaannggeenn--ccrrmm..oorrgg//ccuurrrreenntt//EE3363__VLiisnugauli_sIttiecm_>Object>

パフォーマンスの考慮

初期実装ではGROUP_CONCATを使用してデータを集約していましたが、パフォーマンス問題によりタイムアウトが発生しました。現在はシンプルなクエリを使用し、クライアント側でデータを処理しています:

c}o)nessss)smooom;tiuuuesrrrliscccltieeeLeoUTIamnrimbsUitaer:lgl=iee::b:Udirbabnblitidi:nanind.dndbirigiinen.nngsgsgd.u.o.isleusnmtmrogesicu.l.serslbs?co_ii.eulnov_radnatcbi.lieenvut_lgaeli?sl,em..u?avme.gaa,velpa?u(l.e(uv,beai,lnudei,ng)=>({

2. 階層的な関係の取得

SKOS語彙の階層構造を取得するクエリです。Odeuropaのデータでは、概念間の階層関係が複数の方法で表現されています:

  1. skos:broader - 子から親への参照
  2. skos:narrower - 親から子への参照
  3. skos:topConceptOf - トップコンセプトの宣言

これらすべてに対応するため、UNIONを使用しています:

cc`oo;nnSW}UssEHRttLEB#LERIsgCENmeTDet{(lS?<lms$Uem{rSleuiPllrADli=Re}UQt?>RsLasIeimAaleSrQlcul?he_sPrlmayaerbla=elml)s(.u?grseimt:e(l'slut_rrsiio'nu)gr;)ce=>?s`ource?source_title

0

多言語対応

SKOSのラベルは言語タグ付きで格納されているため、クライアント側で適切な言語を選択します:

cc`oo;nnSW}UssEHRttLEB#LERIsgCENmeTDet{(lS?<lms$Uem{rSleuiPllrADli=Re}UQt?>RsLasIeimAaleSrQlcul?he_sPrlmayaerbla=elml)s(.u?grseimt:e(l'slut_rrsiio'nu)gr;)ce=>?s`ource?source_title

1

パフォーマンス最適化

1. 語彙プレフィックスによるフィルタリング

全体のデータセットから必要なデータのみを取得するため、FILTER(STRSTARTS(...))を使用:

cc`oo;nnSW}UssEHRttLEB#LERIsgCENmeTDet{(lS?<lms$Uem{rSleuiPllrADli=Re}UQt?>RsLasIeimAaleSrQlcul?he_sPrlmayaerbla=elml)s(.u?grseimt:e(l'slut_rrsiio'nu)gr;)ce=>?s`ource?source_title

2

2. 遅延読み込み(Lazy Loading)

階層ツリーでは、初回表示時にトップレベルのみを取得し、ユーザーがノードを展開したときに初めて子ノードを取得します:

cc`oo;nnSW}UssEHRttLEB#LERIsgCENmeTDet{(lS?<lms$Uem{rSleuiPllrADli=Re}UQt?>RsLasIeimAaleSrQlcul?he_sPrlmayaerbla=elml)s(.u?grseimt:e(l'slut_rrsiio'nu)gr;)ce=>?s`ource?source_title

3

3. クエリの事前表示

ユーザーがSPARQLクエリを確認できるよう、結果が返る前からクエリを表示します:

cc`oo;nnSW}UssEHRttLEB#LERIsgCENmeTDet{(lS?<lms$Uem{rSleuiPllrADli=Re}UQt?>RsLasIeimAaleSrQlcul?he_sPrlmayaerbla=elml)s(.u?grseimt:e(l'slut_rrsiio'nu)gr;)ce=>?s`ource?source_title

4

UIとUX

Material-UIによるモダンなデザイン

  • カード型レイアウトによる視認性の向上
  • ホバーエフェクトとトランジション
  • レスポンシブデザイン(Grid / Flexbox)
cc`oo;nnSW}UssEHRttLEB#LERIsgCENmeTDet{(lS?<lms$Uem{rSleuiPllrADli=Re}UQt?>RsLasIeimAaleSrQlcul?he_sPrlmayaerbla=elml)s(.u?grseimt:e(l'slut_rrsiio'nu)gr;)ce=>?s`ource?source_title

5

階層構造の可視化

  • 展開/折りたたみ可能なツリー構造
  • レベルごとの色分け
  • 子コンセプト数の表示
cc`oo;nnSW}UssEHRttLEB#LERIsgCENmeTDet{(lS?<lms$Uem{rSleuiPllrADli=Re}UQt?>RsLasIeimAaleSrQlcul?he_sPrlmayaerbla=elml)s(.u?grseimt:e(l'slut_rrsiio'nu)gr;)ce=>?s`ource?source_title

6

国際化(i18n)

next-intlを使用して英語・日本語に対応:

cc`oo;nnSW}UssEHRttLEB#LERIsgCENmeTDet{(lS?<lms$Uem{rSleuiPllrADli=Re}UQt?>RsLasIeimAaleSrQlcul?he_sPrlmayaerbla=elml)s(.u?grseimt:e(l'slut_rrsiio'nu)gr;)ce=>?s`ource?source_title

7

翻訳ファイルの構造:

cc`oo;nnSW}UssEHRttLEB#LERIsgCENmeTDet{(lS?<lms$Uem{rSleuiPllrADli=Re}UQt?>RsLasIeimAaleSrQlcul?he_sPrlmayaerbla=elml)s(.u?grseimt:e(l'slut_rrsiio'nu)gr;)ce=>?s`ource?source_title

8

ルーティングとナビゲーション

動的パラメータによる柔軟な表示

階層ツリーページでは、URLパラメータで起点となるコンセプトを指定可能:

cc`oo;nnSW}UssEHRttLEB#LERIsgCENmeTDet{(lS?<lms$Uem{rSleuiPllrADli=Re}UQt?>RsLasIeimAaleSrQlcul?he_sPrlmayaerbla=elml)s(.u?grseimt:e(l'slut_rrsiio'nu)gr;)ce=>?s`ource?source_title

9

i18nルーティングの考慮

ロケール対応のルーティングには@/i18n/routinguseRouterを使用:

#?#?#?essmmmieesootlrolssssddilddlkkki::mf:SooooFFeashSosssn31::aKu:::__holsOrpbnahgada_ScrraSaesS:bseeormodnTmLemfared_eie1leaLdol:srml_laewlLoaelS?lsbre1utms_kerE1re?emsol?m_cdtleosb?iSeillu:?rnsm?mlrCpoase?se;LcorarilsmIaenedrolmenbcfeon_elte?eLrwEllelspaCemlrotboriS;v;uenCsoar;lcosulcenire;pcoc.tene.p;t;;.#####

0

データモデル

TypeScript型定義

#?#?#?essmmmieesootlrolssssddilddlkkki::mf:SooooFFeashSosssn31::aKu:::__holsOrpbnahgada_ScrraSaesS:bseeormodnTmLemfared_eie1leaLdol:srml_laewlLoaelS?lsbre1utms_kerE1re?emsol?m_cdtleosb?iSeillu:?rnsm?mlrCpoase?se;LcorarilsmIaenedrolmenbcfeon_elte?eLrwEllelspaCemlrotboriS;v;uenCsoar;lcosulcenire;pcoc.tene.p;t;;.#####

1

SPARQLレスポンスの処理

複数行にわたる同一コンセプトのデータをマージ:

#?#?#?essmmmieesootlrolssssddilddlkkki::mf:SooooFFeashSosssn31::aKu:::__holsOrpbnahgada_ScrraSaesS:bseeormodnTmLemfared_eie1leaLdol:srml_laewlLoaelS?lsbre1utms_kerE1re?emsol?m_cdtleosb?iSeillu:?rnsm?mlrCpoase?se;LcorarilsmIaenedrolmenbcfeon_elte?eLrwEllelspaCemlrotboriS;v;uenCsoar;lcosulcenire;pcoc.tene.p;t;;.#####

2

今後の展望

  1. 検索機能の拡張

    • 全文検索
    • ファセット検索
    • 詳細フィルタ
  2. 可視化の強化

    • ネットワークグラフ
    • タイムライン表示
    • 地理的分布マップ
  3. データの充実

    • 他のSPARQLエンドポイントとの連携
    • Linked Open Dataの活用
    • ユーザー生成コンテンツ

まとめ

本プロジェクトでは、SKOS語彙とSPARQLを活用することで、複雑な階層構造を持つ香りのデータを効果的に可視化しました。セマンティックWebの標準技術を採用することで:

  • データの相互運用性が向上
  • 拡張性の高いアーキテクチャを実現
  • 多言語対応が容易に

今後も、ユーザビリティの向上とデータの充実を図りながら、香りの歴史研究に貢献するプラットフォームを目指します。

リンク


本記事は Claude Code によって生成されました。