はじめに
最近グラフDBを触る機会が増えたので、Apache TinkerPop(以降TinkerPop)という、グラフDBとグラフ分析システムに対応したフレームワークを触ってみました。触ってみるとは言ってもフレームワークなので、扱う対象となるグラフDBが必要となります。ここでは、ApacheのグラフDBであるApache Titan(以降Titan)を試しに入れて使ってみました。
セットアップ
TitanをインストールするのにOracle Java8が必要となるので、事前にインストールしておきます。
あとは、Titanのダウンロードページからダウンロードして、解凍すればすぐに使えるようになります。
具体的には、以下のコマンドでダウンロードして、
$wget -c https://s3.thinkaurelius.com/downloads/titan/titan-1.0.0-hadoop1.zip
unzipします。
$unzip titan-1.0.0-hadoop1.zip
アーキテクチャ
Titanをインストールすると、依存関係のあるTinkerPopもインストールされます。TinkerPopはグラフデータベースを扱うフレームワークとなっており、複数のグラフデータベースをサポートしています。グラフを操作するには、TinkerPopに内包されるgremlinというグラフ操作言語を使用します。以下はTinkerPopのアーキテクチャを示した図で、Graph Databaseの場所にtitanなどのグラフデータベースが位置します。
さっそく使ってみる
では、さっそくですが、クライアントのgremlinのシェルを起動します。
bin/gremlin.sh
Gremlinはグラフ操作言語です。上記で起動したGremlinのシェルはgroovyの実装となっており、シェル内ではgroovyで表現できる文法を使えるようになっています。また、プログラミング言語内に埋め込んだ形でGremlinを使ってグラフが操作できるように、複数の言語に対応したGreamlinの実装ががリリースされています。
サンプルとして用意されているデータを読み込んでざっくりと実際の動きを確認してみます。
gremlin> graph = TitanFactory.open('conf/titan-berkeleyje-es.properties')
gremlin> GraphOfTheGodsFactory.load(graph)
gremlin> g = graph.traversal()
プロパティファイルからグラフのVertices(ノード)とEdges(リレーション)を読み込み、トラバーサル(グラフを操作するためのハンドラ)を取得します。(グラフ用語では、ノードおよびリレーションというものは製品ごとに用語が違っているようなのですが、titanのマニュアルにあわせてVertices(ノード)、Edges(リレーション)と呼ぶことにします。)
GraphOfTheGodsFactory.load()というメソッドを呼び出していますが、これは事前に用意されたJavaのソースコードGraphOfTheGodsFactory.javaがありプロパティファイルからVerticesとEdgesを追加する処理が実装されています。
ここでプロパティファイルから読み込んでGraphOfTheGodsFactory.load()でグラフ構造を生成したサンプルのデータは、以下の図のようになっています。ギリシャ神話の神々の親子関係等をグラフ構造で表したものになっています。このデータに対していろいろ操作を行ってみます。
以下のように、saturnの孫を見つける命令を実行します。
gremlin> g.V(saturn).in('father').in('father').values('name')
==>hercules
Vertices(saturn)からEdgesのfatherを矢印の逆方向に二回たどり、孫のherculesを見つけて名前を表示しています。
各処理は以下のようになっています。
- g:現在のグラフトラバーサルポイント
- V:グラフの全ノードを取得。カッコにノード名が記載されている場合は、特定のノードを取得
- in:Edgesの矢印の逆方向に辿る。
- values(‘name’):nameプロパティの値を取得
この文は以下のようにループを使って表現することができます。
gremlin> hercules = g.V(saturn).repeat(__.in('father')).times(2).next()
また、gremlin上からVertexとEdgeを追加するには以下のようにします。
gremlin> theseus = graph.addVertex('human')
gremlin> theseus.property('name', 'theseus')
gremlin> cerberus = g.V().has('name', 'cerberus').next()
gremlin> battle = theseus.addEdge('battled', cerberus, 'time', 22)
これで、元々のグラフデータに無かった、theseusという人間が追加されました。
gremlin> g.V(hercules).as('h').out('battled').in('battled').where(neq('h')).values('name')
==>theseus
herculesが戦ったmonsterのうち、hercules以外のものの名前を取得すると、登録したtheseusが出力されました。
他にもgremlinのドキュメントを見ると条件式が書けたり、最短経路検索のサンプル等も記載されているので、そこそこの表現力はありそうです。
Visualization
グラフ構造を画面で見る方法がないか探したのですが、見当りませんでした。Titan単体ではグラフ構造をVisualizationする機能は持っていないようです。
TinkerPopのプロバイダ紹介のページにあがっていたなかに、サードパーティー製のVisualizationツールがあるようですので、ご参考までにあげておきます。
フレームワークで対応しているデータベース
Titanの利用しているTinkerPopというグラフデータベース対応フレームワークで対応しているデータベースは以下のようなものがあります。予想外に多かったので、驚きました。実際に試したわけではないのですが、TinkerPopの仕様としては、これらのデータベースに対してgremlinでアクセスすることが出来ます。
- Blazegraph
- Azure Cosmos DB
- DataStax Enterprise Graph
- GRAKN.AI
- IBM Graph
- JanusGraph
- Neo4j
- OrientDB
- Stardog
- Titan
開発ツール
TinkerPopを使ってグラフデータベースにアクセスするアプリケーションの開発ツールとして以下のものも紹介されています。
まとめ
TinkerPopが対応しているグラフデータベースは全てgremlinでアクセス出来るという汎用性の高さがあり、複数のグラフデータベースを扱う場合は、学習コストを低くすることが出来そうな点、対応している開発ツールがあるという点が良さそうです。複数のグラフDBを扱うようなケースでは使ってみるといいかも知れません。