こんにちは。
GWは旧東海道をひたすら歩き続けた(150km)武田です。

今回はグラフデータベース Neo4j なるものを触ってみたいと思います。

そもそもグラフデータベースって何?

  • よく使っているRDBのようなものではなく、グラフ構造のデータを扱うのに特化したデータベース。
  • これだけ読んでもちょっとピンとこないですね。。。複数の関係性を利用したりするのに使うとの事。フェイスブック友達関係などを割り出したり、複数の事柄から最短経路を割り出すときにも向いてるらしいです。

まあ、実際に触ってりながら考えましょう。

実験環境

  • Windows環境下の仮想環境のLINUX
  • OS Centos6
  • Neo4j ver 3.0.1 コミュニティエディション

インストール

  • まずはyumのアップデート
 yum update
  • openjdkのバージョンが古いと動かないようなので新しくします。
まずは古いものを削除
yum remove java-1.6.0-openjdk
yum remove java-1.7.0-openjdk

その上で新しいものをインストール
yum install java-1.8.0-openjdk.x86_64  java-1.8.0-openjdk-src.x86_64            
  • neoj4の展開
tar -xf neo4j-community-3.0.1-unix.tar.gz
※前もってDL済み
  • 設定ファイルを調整
cd neo4j-community-3.0.1
vi ./conf/neo4j.conf

dbms.connector.bolt.address=192.168.24.131:7474
dbms.logs.http.enabled=true
※IPはご自分の環境に合わせてください。
  • neoj4起動
./bin/neo4j start
Starting Neo4j.
WARNING: Max 1024 open files allowed, minimum of 40000 recommended. See the Neo4j manual.
Started neo4j (pid 4116). By default, it is available at http://localhost:7474/
There may be a short delay until the server is ready.
See /home/adjust/neo4j/neo4j-community-3.0.1/logs/neo4j.log for current status.
  • ブラウザでアクセス
    Neo4JにはWebインターフェースがあります。見てみましょう
    gdb1
    なんか立ち上がりましたね。

  • 画面上のコンソールに接続コマンドを入力

:server connect

初期パスワードの設定をしてとりあえず動かせるところまできました!!

触ってみる

簡単な路線検索でも組んでみましょうか。

データベースなので肝心のデータがなくちゃ話が進みませんね。

まずは都営三田線の駅を入れてみましょう。
グラフデータベースの点にあたる[Node]というもので設定していきます。

CREATE文でノードを追加しております。
カッコで囲む形でノードごとにデータ(名前や駅番号)などの要素を加えます。
コマンド自体はSQLと似たり寄ったりな気もします。

※データ投入
CREATE 
(I01:Station { name: "目黒駅", no: "I01" }), 
(I02:Station { name: "白金台駅", no: "I02" }), 
(I03:Station { name: "白金高輪駅", no: "I03" }), 
(I04:Station { name: "三田駅   ", no: "I04" }), 
(I05:Station { name: "芝公園駅", no: "I05" }), 
(I06:Station { name: "御成門駅", no: "I06" }), 
(I07:Station { name: "内幸町駅", no: "I07" }), 
(I08:Station { name: "日比谷駅", no: "I08" }), 
(I09:Station { name: "大手町駅", no: "I09" }), 
(I10:Station { name: "神保町駅", no: "I10" }), 
(I11:Station { name: "水道橋駅", no: "I11" }), 
(I12:Station { name: "春日駅", no: "I12" }), 
(I13:Station { name: "白山駅", no: "I13" }), 
(I14:Station { name: "千石駅", no: "I14" }), 
(I15:Station { name: "巣鴨駅", no: "I15" }), 
(I16:Station { name: "西巣鴨駅", no: "I16" }), 
(I17:Station { name: "新板橋駅", no: "I17" }), 
(I18:Station { name: "板橋区役所前駅", no: "I18" }), 
(I19:Station { name: "板橋本町駅", no: "I19" }), 
(I20:Station { name: "本蓮沼駅", no: "I20" }), 
(I21:Station { name: "志村坂上駅", no: "I21" }), 
(I22:Station { name: "志村三丁目駅", no: "I22" }), 
(I23:Station { name: "蓮根駅", no: "I23" }), 
(I24:Station { name: "西台駅", no: "I24" }), 
(I25:Station { name: "高島平駅", no: "I25" }), 
(I26:Station { name: "新高島平駅", no: "I26" }), 
(I27:Station { name: "西高島平駅", no: "I27" })
RETURN *;

gdb2
おっとなんかでてきましたね。クリックするととブルブル動いてくれます。
リッチコンテンツ感がよいです。

これだと駅があるだけですね。
路線図の様に繋ぎたいです。
ノードという点を繋ぐ[リレーションシップ]を利用しましょう。

※全体をクリア
MATCH (n) OPTIONAL MATCH (n)-[r]-() DELETE n,r;

※データ投入
CREATE 
(I01:Station { name: "目黒駅", no: "I01" }), 
(I02:Station { name: "白金台駅", no: "I02" }), 
(I03:Station { name: "白金高輪駅", no: "I03" }), 
(I04:Station { name: "三田駅   ", no: "I04" }), 
(I05:Station { name: "芝公園駅", no: "I05" }), 
(I06:Station { name: "御成門駅", no: "I06" }), 
(I07:Station { name: "内幸町駅", no: "I07" }), 
(I08:Station { name: "日比谷駅", no: "I08" }), 
(I09:Station { name: "大手町駅", no: "I09" }), 
(I10:Station { name: "神保町駅", no: "I10" }), 
(I11:Station { name: "水道橋駅", no: "I11" }), 
(I12:Station { name: "春日駅", no: "I12" }), 
(I13:Station { name: "白山駅", no: "I13" }), 
(I14:Station { name: "千石駅", no: "I14" }), 
(I15:Station { name: "巣鴨駅", no: "I15" }), 
(I16:Station { name: "西巣鴨駅", no: "I16" }), 
(I17:Station { name: "新板橋駅", no: "I17" }), 
(I18:Station { name: "板橋区役所前駅", no: "I18" }), 
(I19:Station { name: "板橋本町駅", no: "I19" }), 
(I20:Station { name: "本蓮沼駅", no: "I20" }), 
(I21:Station { name: "志村坂上駅", no: "I21" }), 
(I22:Station { name: "志村三丁目駅", no: "I22" }), 
(I23:Station { name: "蓮根駅", no: "I23" }), 
(I24:Station { name: "西台駅", no: "I24" }), 
(I25:Station { name: "高島平駅", no: "I25" }), 
(I26:Station { name: "新高島平駅", no: "I26" }), 
(I27:Station { name: "西高島平駅", no: "I27" }),
(I01)-[:都営三田線]->(I02), (I02)-[:都営三田線]->(I01),
(I02)-[:都営三田線]->(I03), (I03)-[:都営三田線]->(I02),
(I03)-[:都営三田線]->(I04), (I04)-[:都営三田線]->(I03),
(I04)-[:都営三田線]->(I05), (I05)-[:都営三田線]->(I04),
(I05)-[:都営三田線]->(I06), (I06)-[:都営三田線]->(I05),
(I06)-[:都営三田線]->(I07), (I07)-[:都営三田線]->(I06),
(I07)-[:都営三田線]->(I08), (I08)-[:都営三田線]->(I07),
(I08)-[:都営三田線]->(I09), (I09)-[:都営三田線]->(I08),
(I09)-[:都営三田線]->(I10), (I10)-[:都営三田線]->(I09),
(I10)-[:都営三田線]->(I11), (I11)-[:都営三田線]->(I10),
(I11)-[:都営三田線]->(I12), (I12)-[:都営三田線]->(I11),
(I12)-[:都営三田線]->(I13), (I13)-[:都営三田線]->(I12),
(I13)-[:都営三田線]->(I14), (I14)-[:都営三田線]->(I13),
(I14)-[:都営三田線]->(I15), (I15)-[:都営三田線]->(I14),
(I15)-[:都営三田線]->(I16), (I16)-[:都営三田線]->(I15),
(I16)-[:都営三田線]->(I17), (I17)-[:都営三田線]->(I16),
(I17)-[:都営三田線]->(I18), (I18)-[:都営三田線]->(I17),
(I18)-[:都営三田線]->(I19), (I19)-[:都営三田線]->(I18),
(I19)-[:都営三田線]->(I20), (I20)-[:都営三田線]->(I19),
(I20)-[:都営三田線]->(I21), (I21)-[:都営三田線]->(I20),
(I21)-[:都営三田線]->(I22), (I22)-[:都営三田線]->(I21),
(I22)-[:都営三田線]->(I23), (I23)-[:都営三田線]->(I22),
(I23)-[:都営三田線]->(I24), (I24)-[:都営三田線]->(I23),
(I24)-[:都営三田線]->(I25), (I25)-[:都営三田線]->(I24),
(I25)-[:都営三田線]->(I26), (I26)-[:都営三田線]->(I25),
(I26)-[:都営三田線]->(I27), (I27)-[:都営三田線]->(I26)
RETURN *;

gdb3
路線図がつなげました。
グネグネ動いてなんかちょっと新鮮です。
※リレーションシップには関係を示す方向があります。
 電車が一方通行ってことは無いので双方向のリレーションシップとしてます。

三田線だけだと寂しいですね。続いて都営新宿線と山手線もいれて見ましょう。

※全体をクリア
MATCH (n) OPTIONAL MATCH (n)-[r]-() DELETE n,r;

※データ再投入
CREATE 
(I01:Station { name: "目黒駅", no: "I01" }), 
(I02:Station { name: "白金台駅", no: "I02" }), 
(I03:Station { name: "白金高輪駅", no: "I03" }), 
(I04:Station { name: "三田駅   ", no: "I04" }), 
(I05:Station { name: "芝公園駅", no: "I05" }), 
(I06:Station { name: "御成門駅", no: "I06" }), 
(I07:Station { name: "内幸町駅", no: "I07" }), 
(I08:Station { name: "日比谷駅", no: "I08" }), 
(I09:Station { name: "大手町駅", no: "I09" }), 
(I10S06:Station { name: "神保町駅", no: "I10" }), 
(I11:Station { name: "水道橋駅", no: "I11" }), 
(I12:Station { name: "春日駅", no: "I12" }), 
(I13:Station { name: "白山駅", no: "I13" }), 
(I14:Station { name: "千石駅", no: "I14" }), 
(I15JY11:Station { name: "巣鴨駅", no: "I15JY11" }), 
(I16:Station { name: "西巣鴨駅", no: "I16" }), 
(I17:Station { name: "新板橋駅", no: "I17" }), 
(I18:Station { name: "板橋区役所前駅", no: "I18" }), 
(I19:Station { name: "板橋本町駅", no: "I19" }), 
(I20:Station { name: "本蓮沼駅", no: "I20" }), 
(I21:Station { name: "志村坂上駅", no: "I21" }), 
(I22:Station { name: "志村三丁目駅", no: "I22" }), 
(I23:Station { name: "蓮根駅", no: "I23" }), 
(I24:Station { name: "西台駅", no: "I24" }), 
(I25:Station { name: "高島平駅", no: "I25" }), 
(I26:Station { name: "新高島平駅", no: "I26" }), 
(I27:Station { name: "西高島平駅", no: "I27" }),
(I01)-[:三田線]->(I02), (I02)-[:三田線]->(I01),
(I02)-[:三田線]->(I03), (I03)-[:三田線]->(I02),
(I03)-[:三田線]->(I04), (I04)-[:三田線]->(I03),
(I04)-[:三田線]->(I05), (I05)-[:三田線]->(I04),
(I05)-[:三田線]->(I06), (I06)-[:三田線]->(I05),
(I06)-[:三田線]->(I07), (I07)-[:三田線]->(I06),
(I07)-[:三田線]->(I08), (I08)-[:三田線]->(I07),
(I08)-[:三田線]->(I09), (I09)-[:三田線]->(I08),
(I09)-[:三田線]->(I10S06), (I10S06)-[:三田線]->(I09),
(I10S06)-[:三田線]->(I11), (I11)-[:三田線]->(I10S06),
(I11)-[:三田線]->(I12), (I12)-[:三田線]->(I11),
(I12)-[:三田線]->(I13), (I13)-[:三田線]->(I12),
(I13)-[:三田線]->(I14), (I14)-[:三田線]->(I13),
(I14)-[:三田線]->(I15JY11), (I15JY11)-[:三田線]->(I14),
(I15JY11)-[:三田線]->(I16), (I16)-[:三田線]->(I15JY11),
(I16)-[:三田線]->(I17), (I17)-[:三田線]->(I16),
(I17)-[:三田線]->(I18), (I18)-[:三田線]->(I17),
(I18)-[:三田線]->(I19), (I19)-[:三田線]->(I18),
(I19)-[:三田線]->(I20), (I20)-[:三田線]->(I19),
(I20)-[:三田線]->(I21), (I21)-[:三田線]->(I20),
(I21)-[:三田線]->(I22), (I22)-[:三田線]->(I21),
(I22)-[:三田線]->(I23), (I23)-[:三田線]->(I22),
(I23)-[:三田線]->(I24), (I24)-[:三田線]->(I23),
(I24)-[:三田線]->(I25), (I25)-[:三田線]->(I24),
(I25)-[:三田線]->(I26), (I26)-[:三田線]->(I25),
(I26)-[:三田線]->(I27), (I27)-[:三田線]->(I26),
(S01JY17:Station { name: "新宿駅", no: "S01JY17" }), 
(S02:Station { name: "新宿三丁目駅", no: "S02" }), 
(S03:Station { name: "曙橋駅", no: "S03" }), 
(S04:Station { name: "市ヶ谷駅", no: "S04" }), 
(S05:Station { name: "九段下駅", no: "S05" }), 
(S07:Station { name: "小川町駅", no: "S07" }), 
(S08:Station { name: "岩本町駅", no: "S08" }), 
(S09:Station { name: "馬喰横山駅", no: "S09" }), 
(S10:Station { name: "浜町駅", no: "S10" }), 
(S11:Station { name: "森下駅", no: "S11" }), 
(S12:Station { name: "菊川駅", no: "S12" }), 
(S13:Station { name: "住吉駅", no: "S13" }), 
(S14:Station { name: "西大島駅", no: "S14" }), 
(S15:Station { name: "大島駅", no: "S15" }), 
(S16:Station { name: "東大島駅", no: "S16" }), 
(S17:Station { name: "船堀駅", no: "S17" }), 
(S18:Station { name: "一之江駅", no: "S18" }), 
(S19:Station { name: "瑞江駅", no: "S19" }), 
(S20:Station { name: "篠崎駅", no: "S20" }), 
(S21:Station { name: "本八幡駅", no: "S21" }), 
(S01JY17)-[:新宿線]->(S02), (S02)-[:新宿線]->(S01JY17),
(S02)-[:新宿線]->(S03), (S03)-[:新宿線]->(S02),
(S03)-[:新宿線]->(S04), (S04)-[:新宿線]->(S03),
(S04)-[:新宿線]->(S05), (S05)-[:新宿線]->(S04),
(S05)-[:新宿線]->(I10S06), (I10S06)-[:新宿線]->(S05),
(I10S06)-[:新宿線]->(S07), (S07)-[:新宿線]->(I10S06),
(S07)-[:新宿線]->(S08), (S08)-[:新宿線]->(S07),
(S08)-[:新宿線]->(S09), (S09)-[:新宿線]->(S08),
(S09)-[:新宿線]->(S10), (S10)-[:新宿線]->(S09),
(S10)-[:新宿線]->(S11), (S11)-[:新宿線]->(S10),
(S11)-[:新宿線]->(S12), (S12)-[:新宿線]->(S11),
(S12)-[:新宿線]->(S13), (S13)-[:新宿線]->(S12),
(S13)-[:新宿線]->(S14), (S14)-[:新宿線]->(S13),
(S14)-[:新宿線]->(S15), (S15)-[:新宿線]->(S14),
(S15)-[:新宿線]->(S16), (S16)-[:新宿線]->(S15),
(S16)-[:新宿線]->(S17), (S17)-[:新宿線]->(S16),
(S17)-[:新宿線]->(S18), (S18)-[:新宿線]->(S17),
(S18)-[:新宿線]->(S19), (S19)-[:新宿線]->(S18),
(S19)-[:新宿線]->(S20), (S20)-[:新宿線]->(S19),
(S20)-[:新宿線]->(S21), (S21)-[:新宿線]->(S20),
(JY25:Station { name: "品川駅", no: "JY25" }), 
(JY24:Station { name: "大崎駅", no: "JY24" }), 
(JY23:Station { name: "五反田駅", no: "JY23" }), 
(JY22:Station { name: "目黒駅", no: "JY22" }), 
(JY21:Station { name: "恵比寿駅", no: "JY21" }), 
(JY20:Station { name: "渋谷駅", no: "JY20" }), 
(JY19:Station { name: "原宿駅", no: "JY19" }), 
(JY18:Station { name: "代々木駅", no: "JY18" }), 
(JY16:Station { name: "新大久保駅", no: "JY16" }), 
(JY15:Station { name: "高田馬場駅", no: "JY15" }), 
(JY14:Station { name: "目白駅", no: "JY14" }), 
(JY13:Station { name: "池袋駅", no: "JY13" }), 
(JY12:Station { name: "大塚駅", no: "JY12" }), 
(JY10:Station { name: "駒込駅", no: "JY10" }), 
(JY09:Station { name: "田端駅", no: "JY09" }), 
(JY08:Station { name: "西日暮里駅", no: "JY08" }), 
(JY07:Station { name: "日暮里駅", no: "JY07" }), 
(JY06:Station { name: "鶯谷駅", no: "JY06" }), 
(JY05:Station { name: "上野駅", no: "JY05" }), 
(JY04:Station { name: "御徒町駅", no: "JY04" }), 
(JY03:Station { name: "秋葉原駅", no: "JY03" }), 
(JY02:Station { name: "神田駅", no: "JY02" }), 
(JY01:Station { name: "東京駅", no: "JY01" }), 
(JY30:Station { name: "有楽町駅", no: "JY30" }), 
(JY29:Station { name: "新橋駅", no: "JY29" }),
(JY28:Station { name: "浜松町駅", no: "JY28" }),
(JY27:Station { name: "田町駅", no: "JY27" }),
(JY25)-[:山手線]->(JY24), (JY24)-[:山手線]->(JY25),
(JY24)-[:山手線]->(JY23), (JY23)-[:山手線]->(JY24),
(JY23)-[:山手線]->(JY22), (JY22)-[:山手線]->(JY23),
(JY22)-[:山手線]->(JY21), (JY21)-[:山手線]->(JY22),
(JY21)-[:山手線]->(JY20), (JY20)-[:山手線]->(JY21),
(JY20)-[:山手線]->(JY19), (JY19)-[:山手線]->(JY20),
(JY19)-[:山手線]->(JY18), (JY18)-[:山手線]->(JY19),
(JY18)-[:山手線]->(S01JY17), (S01JY17)-[:山手線]->(JY18),
(S01JY17)-[:山手線]->(JY16), (JY16)-[:山手線]->(S01JY17),
(JY16)-[:山手線]->(JY15), (JY15)-[:山手線]->(JY16),
(JY15)-[:山手線]->(JY14), (JY14)-[:山手線]->(JY15),
(JY14)-[:山手線]->(JY13), (JY13)-[:山手線]->(JY14),
(JY13)-[:山手線]->(JY12), (JY12)-[:山手線]->(JY13),
(JY12)-[:山手線]->(I15JY11), (I15JY11)-[:山手線]->(JY12),
(I15JY11)-[:山手線]->(JY10), (JY10)-[:山手線]->(I15JY11),
(JY10)-[:山手線]->(JY09), (JY09)-[:山手線]->(JY10),
(JY09)-[:山手線]->(JY08), (JY08)-[:山手線]->(JY09),
(JY08)-[:山手線]->(JY07), (JY07)-[:山手線]->(JY08),
(JY07)-[:山手線]->(JY06), (JY06)-[:山手線]->(JY07),
(JY06)-[:山手線]->(JY05), (JY05)-[:山手線]->(JY06),
(JY05)-[:山手線]->(JY04), (JY04)-[:山手線]->(JY05),
(JY04)-[:山手線]->(JY03), (JY03)-[:山手線]->(JY04),
(JY03)-[:山手線]->(JY02), (JY02)-[:山手線]->(JY03),
(JY02)-[:山手線]->(JY01), (JY01)-[:山手線]->(JY02),
(JY01)-[:山手線]->(JY30), (JY30)-[:山手線]->(JY01),
(JY30)-[:山手線]->(JY29), (JY29)-[:山手線]->(JY30),
(JY29)-[:山手線]->(JY28), (JY28)-[:山手線]->(JY29),
(JY28)-[:山手線]->(JY27), (JY27)-[:山手線]->(JY28),
(JY27)-[:山手線]->(JY25), (JY25)-[:山手線]->(JY27)
RETURN *;

gdb4
ちょっと見づらいですが登録できました。
青:新宿線
紫:三田線
緑:山手線

これである程度のデータがそろいましたね。

次回

とりあえずはインストールや実験用のデータの準備が整いました。
次回はルート検索や距離の算出などグラフデータベースらしいことをやっていきます。

参考