pikesaku’s blog

個人的なプログラム勉強メモです。記載内容について一切の責任は持ちません。

グラフデータベースNeo4j動作検証

やってみる

 
路線図とかをインプットしてみて最短距離検索とかやる場合、どうやるのかな?
と思っていたら、参考URLがあったので、やってみる!
※正直しっかり理解できてません。。。
 

データ登録スクリプト

 
山手線の路線図を作るだけ。

# -*- coding: utf-8 -*-

import urllib.request as urllib
from xml.dom import minidom, Node
from neo4j.v1 import GraphDatabase, basic_auth


def get_station_info(line_cd):
    join_list = []
    url = 'http://www.ekidata.jp/api/n/' + str(line_cd) + '.xml'
    dom = minidom.parse(urllib.urlopen(url))
    all_station = set()
    all_kukan = dict()
    for join_node in dom.getElementsByTagName('station_join'):
        for join_node_child in join_node.childNodes:
            if join_node_child.nodeType == Node.TEXT_NODE:
                continue
            name = join_node_child.nodeName
            value = join_node_child.childNodes.item(0).nodeValue
            if name == 'station_name1':
                station_name1 = value
                all_station.add(value)
            elif name == 'station_name2':
                station_name2 = value
                all_station.add(value)
        all_kukan[station_name1] = station_name2
    return all_station, all_kukan


def connect_srv():
    driver = GraphDatabase.driver("bolt://localhost", auth=basic_auth('neo4j', 'neo4j'))
    return driver


if __name__ == '__main__':
    all_station, all_kukan = get_station_info(11302)
    driver = connect_srv()

    # Delete Data
    session = driver.session()
    q = 'match (a) optional match (a)-[r]-() delete a,r'
    session.run(q)


    # Add Data
    for station in all_station:
        q = 'create (a:' + station + '{name:' + "'" + station + "'" + '})'
        session.run(q)

    # Add Connectivity
    for src,dst in all_kukan.items():
        q = 'match (a:' + src + '{name:' + "'" + src + "'" + '}), '
        q += '(b:' + dst + '{name:' + "'" + dst + "'" + '}) '
        q += 'merge (a)-[c:rosen]->(b)'
        session.run(q)

    session.close()

 
上記を実行すると、こんなグラフが生成される。
f:id:pikesaku:20170717193330p:plain
 
駅の色に意味なし。neo4jが登録順にラベルの色をつけているためと想定される。
駅間の距離も意味なし。
内・外回りのリレーションを作ろうと思ったが、双方向リレーションを設定するのは、非推奨との情報あり。
Neo4jで学ぶGraph DB入門 - omotenashi-mind
Modelling Data in Neo4j: Bidirectional Relationships
参照時は、方向性を無視した探し方で対応するのが良いとのこと。
 

最短距離を検索

 
GUIから以下クエリを実行

池袋→東京

MATCH (from: 池袋 {name:'池袋'}), (to: 東京 {name:'東京'}), path=allShortestPaths((from)-[*]-(to)) return from,to,path

 
f:id:pikesaku:20170717195954p:plain
 

池袋→新宿

MATCH (from: 池袋 {name:'池袋'}), (to: 新宿 {name:'新宿'}), path=allShortestPaths((from)-[*]-(to)) return from,to,path

 
f:id:pikesaku:20170717200128p:plain