グラフデータベース・クイックスタート

初めてグラフデータベースを使う人のための実践的な入門

グラフデータベースとは

グラフデータベースはグラフ構造を保存・処理する。リレーショナルデータベースでも関係を表現できるが、適切なスキーマ、複雑なクエリ、高コストなJOINが必要になりやすい。グラフデータベースはホワイトボードの図のように接続データを直感的に扱える一方、関係のないデータには適さない。

グラフデータモデル

  • グラフはノードとエッジを持つ。
  • ノードはラベルとKey-Valueプロパティを持つ。
  • エッジはラベル、方向、開始ノード、終了ノードを持つ。
  • エッジもプロパティを持てる。

Dockerで試す

% git clone https://github.com/krlawrence/graph.git
% cd graph/sample-data
% docker run -it --rm -v `pwd`:/mydata tinkerpop/gremlin-console
gremlin> :load /mydata/load-air-routes-graph-34.groovy

Gremlinで探索する

Gremlinのトラバーサルは通常、グラフトラバーサルソースgから始まる。

gremlin> g.V().count()
==>3619
gremlin> g.V().hasLabel('airport').count()
==>3374
gremlin> g.V().hasLabel('airport').has('code','ICN')
==>v[122]
gremlin> g.V().hasLabel('airport').has('code','ICN').valueMap()
==>[country:[KR],code:[ICN],city:[Seoul],icao:[RKSI]]

V()は頂点、hasLabelはラベル、hasはプロパティを絞り込み、valueMapはプロパティを返す。

リレーションシップをたどる

gremlin> g.V().hasLabel('airport').has('code','ICN').out('route').count()
==>144
gremlin> g.V().hasLabel('airport').has('code','ICN').out('route').values('code')
==>BKK
==>SVO
==>HND

乗り継ぎ1回の重複をdedup()で除くと1817空港になる。

gremlin> g.V().hasLabel('airport').has('code','ICN').out('route').out('route').dedup().count()
==>1817

直行便で到達できる空港を除くと1673、仁川から金浦へ戻る2区間ルートは次のように取得できる。

gremlin> g.V().hasLabel('airport').has('code','ICN').out('route').aggregate('nonstop').out('route').where(without('nonstop')).dedup().count()
==>1673
gremlin> g.V().hasLabel('airport').has('code','ICN').out('route').out('route').has('code','GMP').path().by('code')
==>[ICN,HND,GMP]
==>[ICN,KIX,GMP]
==>[ICN,NGO,GMP]

韓国から日本への便を出発空港別に集計する。

gremlin> g.V().hasLabel('airport').has('country','KR').as('kr').out('route').has('country','JP').select('kr').groupCount().by('code')
==>[ICN:27,TAE:5,GMP:3,CJU:4,PUS:6]

最長路線はエッジのdistを並べ替えて取得でき、仁川―新千歳の882マイルである。

gremlin> g.V().hasLabel('airport').has('country','KR').outE('route').order().by('dist',desc).inV().has('country','JP').path().by('code').by('dist')
==>[ICN,882,CTS]

特徴と難しさ

接続データを容易にたどれるが、参照するノードやエッジが数百万規模になると応答は遅くなる。一般的なクエリを効率よく処理できるようグラフを設計し、グラフ保存の利点がないデータは他のデータベースと組み合わせることが重要である。

参考文献