0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

鉄道駅LOD GeoJSONデータをNeo4jに入れる

Last updated at Posted at 2025-03-30

鉄道駅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同士

データ登録用コード

register.py
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のコンソールで例えば六浦と神武寺の間のデータを見ると、下記の通り表示される:
image.png

なお、ノード間の位置関係はAuraが適当に描画しているだけで緯度経度に基づいている訳ではないです。

おわりに

なぜこんなものを作ったか

呑み鉄メインみたいなゆるーい乗り鉄をやっていこうと思っていて、そのための記録アプリを探していたのだが、どうもしっくりくるものがなかった。なので自分で作ってしまおうかと思っている。この記事の内容は、その実現に向けた最初の一歩という感じ。共感いただける方がいたら、連携できそうなことがあれば教えてください。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?