2025年11月17日月曜日

鉄道駅LODをデータベースのRDFグラフにロードし地図上に路線を表示する

オラクル・データベースをRDFグラフのリポジトリとして構成します。構成したRDFグラフに@uedayouさんが作成された鉄道駅LODをロードし、路線をOracle APEXのマップ上に表示してみます。

鉄道駅LOD
https://uedayou.net/jrslod/

東海道新幹線の路線データをデータベースにロードし、APEXのマップ上に表示させてみました。


RDFグラフの作成からAPEXアプリケーションの作成までの、一連の作業を確認します。作業にはこちらの記事「Apache Jena FusekiにOracle Graph Adapterを組み込んだコンテナを作成する」で作成した、Apache Jena Fusekiのコンテナを使用します。このコンテナにはApache Jena以外にorardfldrという、RDFのバルクローダーが含まれています。このorardfldrを使って、鉄道駅LODをデータベースにロードします。

RDFの保存先のデータベースとして、ローカルPCのコンテナとして実行しているOracle AI Database 26ai Freeを使用します。APEXのワークスペースとしてAPEXEV、ワークスペース・スキーマとしてWKSP_APEXDEVが作成済みとします。

作業はSQLワークショップSQLコマンドで実施します。

元にAPEXのワークスペース・スキーマに、RDFネットワークを作成します。名前はLOCALNETとします。

SEM_APIS.CREATE_RDF_NETWORKを実行します。
begin
    sem_apis.create_rdf_network(
        network_name    => 'LOCALNET',
        network_owner   => 'WKSP_APEXDEV',
        tablespace_name => 'USERS'
    );
end;

作成したRDFネットワークを削除する場合は、SEM_APIS.DROP_RDF_NETWORKを実行します。
begin
    sem_apis.drop_rdf_network(
        network_name => 'LOCALNET',
        network_owner => 'WKSP_APEXDEV',
        cascade => false
    );
end;
作成したRDFネットワークにRDFグラフを作成します。名前はRAILWAYSとします。

SEM_APIS.CREATE_RDF_GRAPHを実行します。
begin
    sem_apis.create_rdf_graph(
        rdf_graph_name  => 'RAILWAYS',
        table_name      => null,
        column_name     => null,
        network_name    => 'LOCALNET',
        network_owner   => 'WKSP_APEXDEV'
    );
end;

RDFネットワークLOCALNETに含まれるRDFグラフを確認します。

SELECT * FROM LOCALNET#RDF_MODEL$


RDFグラフを含むRDFネットワークに関するデータベース・オブジェクトの名前には、RDFネットワーク名であるLOCALNET#がプレフィックスとして付与されています。RDFネットワーク名が異なると、RDFグラフの検索先も変わります。

select object_type, object_name from user_objects where object_name like 'LOCALNET#%' order by 1,2


作成したRDFグラフを削除する場合は、SEM_APIS.DROP_RDF_GRAPHを実行します。
begin
    sem_apis.drop_rdf_graph(
        rdf_graph_name => 'RAILWAYS',
        network_name => 'LOCALNET',
        network_owner => 'WKSP_APEXDEV'
    );
end;
鉄道駅LODのデータを手元にダウンロードし、オラクル・データベースにロードします。RDFネットワークLOCALNETおよびRDFグラフRAILWAYSが作成済みとします。

作業ディレクトリを作成し、Apache Jena Fusekiのコンテナを実行します。実行するコンテナの名前はmy-ora-jenaとしています。

podman run -d --name my-ora-jena -p 3030:3030 -v $PWD:/home/oracle/work oracle-jena

ホストの作業ディレクトリをコンテナ内の/home/oracle/workにマウントします。Apache Jena Fusekiにはポート3030で接続できます。

Railways % podman run -d --name my-ora-jena -p 3030:3030 -v $PWD:/home/oracle/work oracle-jena

69ce9090e4de0f3e4235c89433e7572ecc5f307ce636aabbec0682d308d66163

Railways % 


Apache Jena Fusekiが先ほど作成したRDFネットワークLOCALNETおよびRDFグラフRAILWAYSを参照するように、設定ファイルconfig.ttlを更新します。

コンテナmy-ora-jenaに接続します。

podman exec -it my-ora-jena bash

Railways % podman exec -it my-ora-jena bash

[oracle@69ce9090e4de fuseki]$ 


設定ファイル/opt/oracle-jena/fuseki/run/config.ttlを編集します。

vi /opt/oracle-jena/fuseki/run/config.ttl

[oracle@69ce9090e4de fuseki]$ vi /opt/oracle-jena/fuseki/run/config.ttl 


config.ttl内のhostnameport_numbersrvc_namemodel_namenetwork_ownernetwork_nameを置き換えます。model_name、network_owner、network_nameは通常、大文字で指定します。

# Custom code.

[] ja:loadClass "oracle.spatial.rdf.client.jena.assembler.OracleAssemblerVocab" .

oracle:Dataset  rdfs:subClassOf  ja:RDFDataset .


<#oracle> rdf:type oracle:Dataset;

    oracle:connection

    [ a oracle:OracleConnection ;

      oracle:jdbcURL "jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=host.containers.internal)(PORT=1521))(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=freepdb1)))";

      oracle:User "wksp_apexdev" ;

      oracle:Password "wksp_apexdevのパスワード"

    ];

    oracle:allGraphs [ oracle:firstModel "RAILWAYS"; oracle:networkOwner "WKSP_APEXDEV"; oracle:networkName "LOCALNET" ] .



以上を設定した後、コンテナから抜けて再起動します。

[oracle@69ce9090e4de fuseki]$ exit

exit

Railways % podman restart my-ora-jena  

my-ora-jena

Railways % 


Apache Jena Fusekiには、以下のURLでアクセスできます。add dataから、Web画面からRDFデータの追加をできますが、今回はorardfldrを使用します。



東海道新幹線のデータをダウンロードします。

東海道新幹線のページを開きます。このページのURLに拡張子として.ttlを付与し、Turtle形式のデータとしてダウンロードします。



作業はコンテナ内で実施します。コンテナmy-ora-jenaに接続します。接続後、作業ディレクトリへ移動します。

podman exec -it my-ora-jena bash
cd $HOME/work

Railways % podman exec -it my-ora-jena bash

[oracle@69ce9090e4de fuseki]$ cd $HOME/work

[oracle@69ce9090e4de work]$ 


バルクローダーを呼び出せるように、環境変数を設定します。

export ORACLE_JENA_HOME=/opt/oracle-jena
export PATH=$ORACLE_JENA_HOME/bin:$PATH

[oracle@69ce9090e4de work]$ export ORACLE_JENA_HOME=/opt/oracle-jena

[oracle@69ce9090e4de work]$ export PATH=$ORACLE_JENA_HOME/bin:$PATH

[oracle@69ce9090e4de work]$ 


東海道新幹線.ttlをダウンロードします。wgetコマンドを使用します。

wget -x -nc https://uedayou.net/jrslod/%E6%9D%B1%E6%B5%B7%E6%97%85%E5%AE%A2%E9%89%84%E9%81%93/%E6%9D%B1%E6%B5%B7%E9%81%93%E6%96%B0%E5%B9%B9%E7%B7%9A.ttl

以下の位置に保存されます。

uedayou.net/jrslod/東海旅客鉄道/東海道新幹線.ttl

[oracle@69ce9090e4de work]$ wget -x -nc https://uedayou.net/jrslod/%E6%9D%B1%E6%B5%B7%E6%97%85%E5%AE%A2%E9%89%84%E9%81%93/%E6%9D%B1%E6%B5%B7%E9%81%93%E6%96%B0%E5%B9%B9%E7%B7%9A.ttl

--2025-11-17 07:01:40--  https://uedayou.net/jrslod/%E6%9D%B1%E6%B5%B7%E6%97%85%E5%AE%A2%E9%89%84%E9%81%93/%E6%9D%B1%E6%B5%B7%E9%81%93%E6%96%B0%E5%B9%B9%E7%B7%9A.ttl

Resolving uedayou.net (uedayou.net)... 49.212.223.188

Connecting to uedayou.net (uedayou.net)|49.212.223.188|:443... connected.

HTTP request sent, awaiting response... 200 OK

Length: unspecified [text/turtle]

Saving to: ‘uedayou.net/jrslod/東海旅客鉄道/東海道新幹線.ttl’


uedayou.net/jrslod/東海旅客鉄道/東海      [ <=>                                                                      ] 124.87K  --.-KB/s    in 0.1s    


2025-11-17 07:01:41 (1.21 MB/s) - ‘uedayou.net/jrslod/東海旅客鉄道/東海道新幹線.ttl’ saved [127864]


[oracle@69ce9090e4de work]$ 


バルクローダーを実行し、東海道新幹線.ttlをRDFグラフRAILWAYSにアップロードします。--fileDirにはttlファイルではなく、ttlファイルを含むディレクトリを指定します。
orardfldr --modelName=RAILWAYS --fileDir=./uedayou.net/jrslod/東海旅客鉄道 \
--lang=TURTLE --jdbcUrl="jdbc:oracle:thin:@host.containers.internal:1521/freepdb1" \
--user=WKSP_APEXDEV --password=<パスワード> \
--networkName=LOCALNET --networkOwner=WKSP_APEXDEV

[oracle@479a913ee992 work]$ orardfldr --modelName=RAILWAYS --fileDir=./uedayou.net/jrslod/東海旅客鉄道 \

> --lang=TURTLE --jdbcUrl="jdbc:oracle:thin:@host.containers.internal:1521/freepdb1" \

> --user=WKSP_APEXDEV --password=oracle \

> --networkName=LOCALNET --networkOwner=WKSP_APEXDEV

log4j:WARN No appenders could be found for logger (oracle.spatial.rdf.client.jena.Parameters).

log4j:WARN Please initialize the log4j system properly.

log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.

loadRDF: enabling parallel DDL/DML/query for session [0]

loadRDF: truncating staging tables

loadRDF in parallel: PrepareWorker [0] running

PrepareWorker: thread [0] done to 0, file = ./uedayou.net/jrslod/東海旅客鉄道/東海道新幹線.ttl in (ms) 956

loadRDF: preparing for bulk load

loadRDF: starting bulk load

loadRDF: bulk load flags="PARSE"

loadRDF: bulk load completed in (ms) 1079

[oracle@479a913ee992 work]$ 


Apache Jena Fusekiに接続し、アップロードしたデータを確認します。

queryを開きます。


以下のSPARQLクエリを実行し、路線のジオメトリを取得します。
PREFIX gsp: <http://www.opengis.net/ont/geosparql#>
SELECT ?s ?p ?o
WHERE {
  <https://uedayou.net/jrslod/東海旅客鉄道/東海道新幹線> gsp:asWKT ?o
}

以上で東海道新幹線の路線データを、RDFグラフとしてアップロードできました。

APEXアプリケーションを作成し、マップ上に東海道新幹線の路線を表示します。

SQLコマンドから、マップソースとして使用するSELECT文を実行します。
select t.s$rdfterm name, sdo_util.from_wktgeometry(t.o$rdfclob) geom
from table(sem_match(
    query => q'[
        SELECT ?s ?o
        WHERE
        { ?s gsp:asWKT ?o }
    ]'
    , models => SEM_MODELS('RAILWAYS')
    , rulebases => null
    , aliases => SEM_ALIASES(
        SEM_ALIAS('gsp','http://www.opengis.net/ont/geosparql#')
    )
    , filter => null
    , options =>' PLUS_RDFT=VC '
    , network_owner => 'WKSP_APEXDEV'
    , network_name => 'LOCALNET'
)) t
where t.s$rdfterm = '<https://uedayou.net/jrslod/東海旅客鉄道/東海道新幹線>';

空のアプリケーションを作成します。名前鉄道駅とします。


アプリケーションが作成されます。ページ・デザイナでホーム・ページを開きます。


新たにリージョンを作成します。識別名前鉄道駅タイプマップとします。


属性タブを開き、属性コピーライトとして以下を記述します。
<a href="https://uedayou.net/">&copy; uedayou</a>&nbsp;
<a href="https://www.maptiler.com/copyright">&copy; MapTiler</a>&nbsp;
<a href="https://www.openstreetmap.org/copyright">&copy; OpenStreetMap contributors</a>

レイヤーを選択し、識別名前路線レイヤー・タイプに変更します。

ソースタイプSQL問合せとし、SQL問合せに先ほどSQLコマンドで実行したSELECT文を記述します。列のマップングジオメトリ列GEOM主キー列NAMEを選択します。


以上でAPEXアプリケーションは完成です。

アプリケーションを実行すると、記事の先頭のスクリーンショットのように、東海道新幹線の路線がマップ上に表示されます。

今回作成したAPEXアプリケーションのエクスポートを以下に置きました。
https://github.com/ujnak/apexapps/blob/master/exports/rdf-graph-for-railway-station-lod.zip

Oracle APEXのアプリケーション作成の参考になれば幸いです。