11はじめてのグラフデータベースGraphDBGremlin皆さん、グラフデータベースは利用していますか?この記事ではグラフデータベースを触ったことがない人向けにグラフデータベースの基本的な使い方を説明していきます。2019の11日目です。Diverseではマッチングアプリのレコメンドにグラフデータベースを利用しています。グラフデータベースとは?グラフデータベースは名前の通りグラフを扱うデータベースです。使われているリレーショナルデータベースは表構造を扱うデータベースと言えます。リレーショナルデータベースは、複数の表構造の関係を扱えますが、実際に関係を扱うのは難しいことが多いです。関係を表すために適切なスキーマ設計が必要になり、クエリは難しくなりがちです。表を結合するにはコストがかかります。グラフデータベースは、ホワイトボードに図を書く感覚でデータを扱えることが利点です。繋がりのあるデータを直感的に操作できます。逆に繋がりのないデータを扱うことには向いていません。グラフのデータモデル一般的によく使われているのはプロパティグラフで、プロパティグラフは以下の特徴があります。グラフにはノード(頂点)とエッジ(辺)がありますノードにはラベルとプロパティ(キーと値のペア)がありますエッジにはラベルと方向があり開始ノードと終了ノードがあります。エッジにももちろんプロパティを含めることができます。実際にグラフデータベースを使ってみようグラフデータベースを理解するには実際に使ってみるのが早いです。Dockerを利用するため、事前にDockerのインストールが必要です。グラフデータベースを使うための準備サンプルデータをクローンする実際にグラフからデータを引いてみるのが分かりやすいため、サンプルデータをクローンします。Tutorialで利用されている航空路のデータです。https://github.com/krlawrence/graph.gitグラフストアを起動し、サンプルデータをロードするDockerでグラフデータベースを起動し、サンプルデータをロードします。Dockerイメージは、tinkerpop/gremlin-consoleを利用します。Consoleには、TinkerGraphと呼ばれるオンメモリのグラフストアが付属しています。/mydata/load-air-routes-graph.groovyグラフを探索するGremlinリレーショナルデータベースで使われるSQLの様に、グラフデータベースのためのクエリ言語はいくつかあります。この記事では、Gremlinを利用します。Gremlinでは、メソッドチェーンのような記述でグラフを辿ります。グラフを辿るGremlinでは、クエリは基本的にgから開始します。これはグラフにアクセスするためのトラバーサルオブジェクトと呼ばれるものです。このトラバーサルオブジェクトは自分で好きな変数に割り当てることができますが、gという変数にバインドすることが多いです。サンプルデータをロードした時点で既にgにバインドされています。クエリノードの取得サンプルデータの航空路のデータを辿っていきましょう。g.V()==>v[0]==>v[1]==>v[2]==>v[3]==>v[4]==>v[5]==>v[6]==>v[7]==>v[8]==>v[9]...当然ながら大量のノードが返されます。絞り込んで取得してみましょう。g.V().count()==>3619ノードはラベルで絞らないと、空港以外のノードも返ってくるので空港(airport)のノードだけの件数を数えてみます。hasLabelでラベルで絞り込むことができます。g.V().hasLabel('airport').count()==>3374羽田空港の空港コード(HND)を持つを空港を探してみます。hasでプロパティのキーと値を渡すことで絞り込むことができます。g.V().hasLabel('airport').has('code','HND')==>v[105]1つだけのノードが取得できました!羽田空港のノードがどのようなプロパティを持っているか見てみましょう。Airport]]ノードを辿るoutを利用して、出ていく方向の頂点やエッジを調べられます。空港と空港はrouteというラベルのエッジで結ばれているので、羽田空港から出ていくルートの数を数えてみます。g.V().hasLabel('airport').has('code','HND').out('route').count()==>8282のルートがあることがわかります。実際にどの空港へ行くのか見てみましょう。プロパティの値を取得するには、valuesを利用します。キー名を渡すことで特定のプロパティの値を取得できます。g.V().hasLabel('airport').has('code','HND').out('route').out('route').count()==>4924登録されている空港の数より多い数が返ってきました。これは重複が除去されていないためです。重複を除去するにはdedupを使います。g.V().hasLabel('airport').has('code','HND').out('route').out('route').dedup().count()==>1247さらに乗り換えを1回使うが、直行で行けるルートを除去してみます。aggregateで一時的にコレクションを保存して、whereで除去します。'NRT').path().by('code')==>[HND,KMQ,NRT]==>[HND,YGJ,NRT]==>[HND,MYJ,NRT]==>[HND,TAK,NRT]==>[HND,OKA,NRT]==>[HND,HKD,NRT]==>[HND,JFK,NRT]==>[HND,LAX,NRT]==>[HND,ORD,NRT]==>[HND,SEA,NRT]...小松空港(KMQ)などを経由するルートが一覧で返ってきました。ノードを辿る日本とアメリカを結ぶ空港のルートを取ってみます。g.V().hasLabel('airport').has('country','JP').out('route').has('country','US').path().by('code')==>[NRT,PDX]==>[NRT,KOA]==>[NRT,ATL]==>[NRT,BOS]==>[NRT,DFW]==>[NRT,IAD]==>[NRT,IAH]==>[NRT,JFK]==>[NRT,LAX]==>[NRT,ORD]==>[NRT,SEA]==>[NRT,SFO]==>[NRT,SJC]==>[NRT,SAN]==>[NRT,DEN]==>[NRT,EWR]==>[NRT,HNL]==>[NRT,DTW]==>[HND,JFK]==>[HND,LAX]==>[HND,MSP]==>[HND,ORD]==>[HND,SEA]==>[HND,SFO]==>[HND,HNL]==>[FUK,HNL]==>[KIX,JFK]==>[KIX,LAX]==>[KIX,SFO]==>[KIX,HNL]==>[CTS,HNL]==>[NGO,HNL]==>[NGO,DTW]ほとんどが羽田発と成田発です。分かりやすいようにカウントしてみましょう。どこでグルーピングするか分かるように途中でasで名前を付けて参照する必要があります。out('route').has('country','US').select('jp').groupCount().by('code')==>[NRT:18,CTS:1,NGO:2,KIX:4,FUK:1,HND:7]アメリカへ行くルートは成田空港発が18つ、羽田空港発が7つあることが分かりました。日本とアメリカの最長ルートはどこでしょうか?各エッジには距離があるためそれを参照して調べてみましょうエッジに注目したいので、outではなくoutEとinVを使い、orderで並び替えてみます。path().by('code').by('dist')==>[KIX,6926,JFK]==>[NRT,6832,ATL]==>[HND,6753,JFK]==>[NRT,6734,IAD]==>[NRT,6725,JFK]==>[NRT,6712,EWR]...関西国際空港(KIX)とジョン・F・ケネディ国際空港(JFK)を結ぶ6926マイルが最長であることがわかります。グラフデータベースの得意なこと、苦手なこと実際にグラフデータベースを触ってみると、繋がりのあるデータを容易に引くことが出来ると分かります。グラフデータベースだからといって何でも引くことが出来るわけではありません。グラフデータベースでも参照するノードやエッジ数が増えればレスポンスは悪化します。数百万フォロワーいる有名人が存在するソーシャルグラフの場合、その有名人をフォローしているという条件から始めてトラバーサルしていくと、数百万エッジを参照することになるので即時に結果を返すことは難しくなります。効率的なクエリを書くことはもちろん重要ですが、システムとして利用する予定の一般的なクエリを効率的に捌けるようにグラフを配置する必要があります。グラフに全てのデータを保存する必要はなく、他のデータベースシステムと組み合わせて適材適所で利用することが重要です。データとして関係性を扱っているけど、MySQLでJOINするのが辛くなってきた方はぜひ一度グラフデータベースを利用してみてください。TOMA@Amothichttp://amothic.comFollow株式会社Diverse結婚支援事業を中心に、友達・恋人探しのマッチング事業を展開。深刻化する恋愛離れ、未婚率の上昇を解決すべくWEB・アプリサービスを展開。すべての人へ出会いのプラットフォームを提供しています。upLoginユーザーは見つかりませんでした。