鉄道駅LOD GeoJSON ダウンローダーから取得した路線位置情報のJSONデータを、メジャーなグラフDBであるNeo4jに格納するということをやってみた。
環境
- Python 3.13.2
- Neo4j Aura
- Neo4j Python driver
準備
Neo4j Aura
Neo4jを使うのが初めてだったので、手軽に使えるAuraのフリーアカウントを利用しました。Neo4jのサイトから「Get Started Free」→ログイン→「Creating your instance」。
自分用のURLやパスワードが書かれたファイルをダウンロードできるので保存しておく。
Pythonライブラリ
- pip install neo4j
GeoJSONファイル
鉄道駅LOD GeoJSON ダウンローダーから様々な鉄道会社の様々な路線のデータをダウンロードできるが、ここではとりあえず京急の逗子線のみ対象にします。
京浜急行電鉄京急逗子線.geojson をダウンロードして保存しておく。
実装
グラフの設計
- Pointノード:緯度経度で示される点
- 経度longitude、緯度latitudeというプロパティを持つ
- 駅がある地点の場合はstation_nameというプロパティで駅名を保持
- Connectedリレーションシップ:線路で直接つながっているPoint同士
データ登録用コード
from neo4j import GraphDatabase
import json
AURA_CONNECTION_URI="neo4j+s://xxxxxxx.databases.neo4j.io" # 自分用URL
AURA_USERNAME="neo4j"
AURA_PASSWORD="yyyyyyy" # 自分のパスワード
class Driver:
driver = GraphDatabase.driver(AURA_CONNECTION_URI, auth=(AURA_USERNAME, AURA_PASSWORD))
@classmethod
def get_session(cls):
return cls.driver.session()
# GeoJSONデータをJSONファイルから読み込む
with open('../京浜急行電鉄京急逗子線.geojson', 'r', encoding='utf-8') as f:
geojson = json.load(f)
# geojsonのデータをNeo4jに登録
with Driver.get_session() as session:
# 既存のノードを削除
session.run("MATCH (n) DETACH DELETE n")
# GeoJSONデータをNeo4jに登録
for feature in geojson['features']:
type = feature['geometry']['type']
name = feature['properties']['name']
coordinates = feature['geometry']['coordinates']
if type == 'Point':
session.run(f"""
MERGE (p:Point {{longitude: '{coordinates[0]}', latitude: '{coordinates[1]}'}})
SET p.station_name = '{name}'
""")
elif type == 'MultiLineString':
for line_string in coordinates:
# 各座標をPointノードとして登録するとともに、座標間をLineノードで結ぶ
for i in range(len(line_string) - 1):
start_coord = line_string[i]
end_coord = line_string[i + 1]
session.run(f"""
MERGE (p1:Point {{longitude: '{start_coord[0]}', latitude: '{start_coord[1]}'}})
MERGE (p2:Point {{longitude: '{end_coord[0]}', latitude: '{end_coord[1]}'}})
MERGE (p1)-[:Connected]-(p2)
""")
GeoJSONにはMultiLineStringだけでなくLineStringというtypeのデータも含まれるのだが、MultiLineStringに包含される冗長なデータのようなので使っていない。
結果
Auraのコンソールで例えば六浦と神武寺の間のデータを見ると、下記の通り表示される:
なお、ノード間の位置関係はAuraが適当に描画しているだけで緯度経度に基づいている訳ではないです。
おわりに
なぜこんなものを作ったか
呑み鉄メインみたいなゆるーい乗り鉄をやっていこうと思っていて、そのための記録アプリを探していたのだが、どうもしっくりくるものがなかった。なので自分で作ってしまおうかと思っている。この記事の内容は、その実現に向けた最初の一歩という感じ。共感いただける方がいたら、連携できそうなことがあれば教えてください。