こんにちは。武田です。
今回もグラフデータベース Neo4j 触ってみたいと思います。

検索

前回は駅と路線データを準備したので検索してみましょう

  • まずは単純に駅名で検索。新宿駅を探してみましょう
MATCH (s:Station) WHERE s.name = "新宿駅" RETURN s;

gdb5
あっさりとできました。

  • 次は全体から駅名だけを抜き出してみましょう
    collect関数で絞込をします。mysqlのselectみたいですね
MATCH (n:Station)
RETURN collect(n.name)

gdb9

  • 都営新宿線だけを抜き出す
    リレーション:新宿線を検索対象にします。
MATCH p=()-[r:`新宿線`]->() RETURN p LIMIT 50

gdb10

  • 路線検索をしてみましょう
    ではではそろそろグラフデータベースらしいことをしましょう。
    三田線:神保町駅から三田線:巣鴨駅へ行くにはどうしたらいいでしょうか?

開始地点を”神保町駅” , 終了を “巣鴨駅”に設定。
最短距離を取得するallShortestPathsを利用します。

match (start: Station { name: "神保町駅" }), (end: Station {name: "巣鴨駅" }),
path=allShortestPaths((start)-[*]-(end))
return start, end, path
LIMIT 50;

gdb6

  • 難易度も上げてみて複数の路線だとどうでしょうか?
    三田線:西台駅から新宿駅へ行くにはどうしたらいいでしょうか?
match (start: Station { name: "西台駅" }), (end: Station {name: "新宿駅" }),
path=allShortestPaths((start)-[*]-(end))
return start, end, path
LIMIT 50;

gdb7
good!
巣鴨駅で三田線->山手線の乗り換えも表現できてますね。
ほかのルートもありますがきちんと最短ルートです!

移動距離の計算

もうちょっと踏み込んだこともやってみましょう。
路線検索なので距離の計算とかもしたいですね。
※最初は金額計算とか考えてましたけどおぞましいほど複雑なので諦めました!

  • データの準備
    neo4jではノードやリレーションに対してプロパティという形でデータを持たせることができます。
    駅をつないでいるリレーションに対して移動距離を追加しましょう。
    今回は距離(distance)を追加しました。
※全体をクリア
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)-[:三田線    {distance: 1.3}]->(I02), (I02)-[:三田線         {distance: 1.3}]->(I01),
(I02)-[:三田線    {distance: 1}]->(I03), (I03)-[:三田線         {distance: 1}]->(I02),
(I03)-[:三田線    {distance: 1.7}]->(I04), (I04)-[:三田線         {distance: 1.7}]->(I03),
(I04)-[:三田線    {distance: 0.6}]->(I05), (I05)-[:三田線         {distance: 0.6}]->(I04),
(I05)-[:三田線    {distance: 0.7}]->(I06), (I06)-[:三田線         {distance: 0.7}]->(I05),
(I06)-[:三田線    {distance: 1.1}]->(I07), (I07)-[:三田線         {distance: 1.1}]->(I06),
(I07)-[:三田線    {distance: 0.9}]->(I08), (I08)-[:三田線         {distance: 0.9}]->(I07),
(I08)-[:三田線    {distance: 0.9}]->(I09), (I09)-[:三田線         {distance: 0.9}]->(I08),
(I09)-[:三田線    {distance: 1.4}]->(I10S06), (I10S06)-[:三田線   {distance: 1.4}]->(I09),
(I10S06)-[:三田線 {distance: 1}]->(I11), (I11)-[:三田線         {distance: 1}]->(I10S06),
(I11)-[:三田線    {distance: 0.7}]->(I12), (I12)-[:三田線         {distance: 0.7}]->(I11),
(I12)-[:三田線    {distance: 1.4}]->(I13), (I13)-[:三田線         {distance: 1.4}]->(I12),
(I13)-[:三田線    {distance: 1}]->(I14), (I14)-[:三田線         {distance: 1}]->(I13),
(I14)-[:三田線    {distance: 0.9}]->(I15JY11), (I15JY11)-[:三田線 {distance: 0.9}]->(I14),
(I15JY11)-[:三田線{distance: 1.4}]->(I16), (I16)-[:三田線         {distance: 1.4}]->(I15JY11),
(I16)-[:三田線    {distance: 1}]->(I17), (I17)-[:三田線         {distance: 1}]->(I16),
(I17)-[:三田線    {distance: 0.9}]->(I18), (I18)-[:三田線         {distance: 0.9}]->(I17),
(I18)-[:三田線    {distance: 1.2}]->(I19), (I19)-[:三田線         {distance: 1.2}]->(I18),
(I19)-[:三田線    {distance: 0.9}]->(I20), (I20)-[:三田線         {distance: 0.9}]->(I19),
(I20)-[:三田線    {distance: 1.1}]->(I21), (I21)-[:三田線         {distance: 1.1}]->(I20),
(I21)-[:三田線    {distance: 0.9}]->(I22), (I22)-[:三田線         {distance: 0.9}]->(I21),
(I22)-[:三田線    {distance: 1.2}]->(I23), (I23)-[:三田線         {distance: 1.2}]->(I22),
(I23)-[:三田線    {distance: 0.8}]->(I24), (I24)-[:三田線         {distance: 0.8}]->(I23),
(I24)-[:三田線    {distance: 1}]->(I25), (I25)-[:三田線         {distance: 1}]->(I24),
(I25)-[:三田線    {distance: 0.7}]->(I26), (I26)-[:三田線         {distance: 0.7}]->(I25),
(I26)-[:三田線    {distance: 0.8}]->(I27), (I27)-[:三田線         {distance: 0.8}]->(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)-[:新宿線 {distance: 0.8}]->(S02), (S02)-[:新宿線       {distance: 0.8}]->(S01JY17),
(S02)-[:新宿線     {distance: 1.5}]->(S03), (S03)-[:新宿線       {distance: 1.5}]->(S02),
(S03)-[:新宿線     {distance: 1.4}]->(S04), (S04)-[:新宿線       {distance: 1.4}]->(S03),
(S04)-[:新宿線     {distance: 1.3}]->(S05), (S05)-[:新宿線       {distance: 1.3}]->(S04),
(S05)-[:新宿線     {distance: 0.6}]->(I10S06), (I10S06)-[:新宿線 {distance: 0.6}]->(S05),
(I10S06)-[:新宿線  {distance: 0.9}]->(S07), (S07)-[:新宿線       {distance: 0.9}]->(I10S06),
(S07)-[:新宿線     {distance: 0.8}]->(S08), (S08)-[:新宿線       {distance: 0.8}]->(S07),
(S08)-[:新宿線     {distance: 0.8}]->(S09), (S09)-[:新宿線       {distance: 0.8}]->(S08),
(S09)-[:新宿線     {distance: 0.6}]->(S10), (S10)-[:新宿線       {distance: 0.6}]->(S09),
(S10)-[:新宿線     {distance: 0.8}]->(S11), (S11)-[:新宿線       {distance: 0.8}]->(S10),
(S11)-[:新宿線     {distance: 0.8}]->(S12), (S12)-[:新宿線       {distance: 0.8}]->(S11),
(S12)-[:新宿線     {distance: 0.9}]->(S13), (S13)-[:新宿線       {distance: 0.9}]->(S12),
(S13)-[:新宿線     {distance: 1}]->(S14), (S14)-[:新宿線       {distance: 1}]->(S13),
(S14)-[:新宿線     {distance: 0.7}]->(S15), (S15)-[:新宿線       {distance: 0.7}]->(S14),
(S15)-[:新宿線     {distance: 1.2}]->(S16), (S16)-[:新宿線       {distance: 1.2}]->(S15),
(S16)-[:新宿線     {distance: 1.7}]->(S17), (S17)-[:新宿線       {distance: 1.7}]->(S16),
(S17)-[:新宿線     {distance: 1.7}]->(S18), (S18)-[:新宿線       {distance: 1.7}]->(S17),
(S18)-[:新宿線     {distance: 1.7}]->(S19), (S19)-[:新宿線       {distance: 1.7}]->(S18),
(S19)-[:新宿線     {distance: 1.5}]->(S20), (S20)-[:新宿線       {distance: 1.5}]->(S19),
(S20)-[:新宿線     {distance: 2.8}]->(S21), (S21)-[:新宿線       {distance: 2.8}]->(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)-[:山手線    {distance: 2.2}]->(JY24), (JY24)-[:山手線       {distance: 2.2}]->(JY25),
(JY24)-[:山手線    {distance: 2}]->(JY23), (JY23)-[:山手線       {distance: 2}]->(JY24),
(JY23)-[:山手線    {distance: 0.9}]->(JY22), (JY22)-[:山手線       {distance: 0.9}]->(JY23),
(JY22)-[:山手線    {distance: 1.2}]->(JY21), (JY21)-[:山手線       {distance: 1.2}]->(JY22),
(JY21)-[:山手線    {distance: 1.5}]->(JY20), (JY20)-[:山手線       {distance: 1.5}]->(JY21),
(JY20)-[:山手線    {distance: 1.6}]->(JY19), (JY19)-[:山手線       {distance: 1.6}]->(JY20),
(JY19)-[:山手線    {distance: 1.2}]->(JY18), (JY18)-[:山手線       {distance: 1.2}]->(JY19),
(JY18)-[:山手線    {distance: 1.5}]->(S01JY17), (S01JY17)-[:山手線 {distance: 1.5}]->(JY18),
(S01JY17)-[:山手線 {distance: 0.7}]->(JY16), (JY16)-[:山手線       {distance: 0.7}]->(S01JY17),
(JY16)-[:山手線    {distance: 1.3}]->(JY15), (JY15)-[:山手線       {distance: 1.3}]->(JY16),
(JY15)-[:山手線    {distance: 1.4}]->(JY14), (JY14)-[:山手線       {distance: 1.4}]->(JY15),
(JY14)-[:山手線    {distance: 0.9}]->(JY13), (JY13)-[:山手線       {distance: 0.9}]->(JY14),
(JY13)-[:山手線    {distance: 1.2}]->(JY12), (JY12)-[:山手線       {distance: 1.2}]->(JY13),
(JY12)-[:山手線    {distance: 1.8}]->(I15JY11), (I15JY11)-[:山手線 {distance: 1.8}]->(JY12),
(I15JY11)-[:山手線 {distance: 1.1}]->(JY10), (JY10)-[:山手線       {distance: 1.1}]->(I15JY11),
(JY10)-[:山手線    {distance: 0.7}]->(JY09), (JY09)-[:山手線       {distance: 0.7}]->(JY10),
(JY09)-[:山手線    {distance: 1.6}]->(JY08), (JY08)-[:山手線       {distance: 1.6}]->(JY09),
(JY08)-[:山手線    {distance: 0.8}]->(JY07), (JY07)-[:山手線       {distance: 0.8}]->(JY08),
(JY07)-[:山手線    {distance: 0.5}]->(JY06), (JY06)-[:山手線       {distance: 0.5}]->(JY07),
(JY06)-[:山手線    {distance: 1.1}]->(JY05), (JY05)-[:山手線       {distance: 1.1}]->(JY06),
(JY05)-[:山手線    {distance: 1.1}]->(JY04), (JY04)-[:山手線       {distance: 1.1}]->(JY05),
(JY04)-[:山手線    {distance: 0.6}]->(JY03), (JY03)-[:山手線       {distance: 0.6}]->(JY04),
(JY03)-[:山手線    {distance: 1}]->(JY02), (JY02)-[:山手線       {distance: 1}]->(JY03),
(JY02)-[:山手線    {distance: 0.7}]->(JY01), (JY01)-[:山手線       {distance: 0.7}]->(JY02),
(JY01)-[:山手線    {distance: 1.3}]->(JY30), (JY30)-[:山手線       {distance: 1.3}]->(JY01),
(JY30)-[:山手線    {distance: 0.8}]->(JY29), (JY29)-[:山手線       {distance: 0.8}]->(JY30),
(JY29)-[:山手線    {distance: 1.1}]->(JY28), (JY28)-[:山手線       {distance: 1.1}]->(JY29),
(JY28)-[:山手線    {distance: 1.2}]->(JY27), (JY27)-[:山手線       {distance: 1.2}]->(JY28),
(JY27)-[:山手線    {distance: 1.5}]->(JY25), (JY25)-[:山手線       {distance: 1.5}]->(JY27)
RETURN *;                                                                                
  • 距離の算出
    前回とほぼ同じですが returnに REDUCE関数 を追加しております。集計対象に対して計算をかけるための関数です。
match (start: Station { name: "西台駅" }), (end: Station {name: "新宿駅" }),
path=allShortestPaths((start)-[rel*]-(end))
return path, reduce(totalProp = 0, relcol in rel | totalProp + relcol.distance) as total
LIMIT 1;

gdb8
totalが[ 16.7 ] ですね。
無事 西台駅-> 新宿駅の各リレーションごとのdistanceを集計した結果が取れてますね。

いやはやグラフデータベースはなかなかにスゴイですね。
何に使うかは考えどころですがちょっと触ってみてもいいかもです。

参考