2014年5月11日日曜日

[Gremlin] OrientDBをGremlinから使うとaddEdgeしても反応がない!?

OrientDBは、オープンソースのグラフDB(かつドキュメントDB)である。
グラフDBといえばNeo4jなんだけど、やんごとなき事情によりOrientDBを使ってみることにしたらタイトルの件でハマった。

簡単な用語説明

グラフとは?:

Excelのアレではなく、点と点を線が結ぶアレ。

グラフDBとは?:

いわゆるDBであるところのRDB(MySQLとか)は、データを表形式として扱うようデザインされている。
グラフDBは、データを点と点と線の繋がりとして扱うようにデザインされている。
データの一覧を上から下まで流し見るようなクエリは苦手だが、あなたの買った本を買ったユーザが買った本の・・・みたいに、繋がりをずるずると解決していくようなクエリが得意。

Gremlinとは?:

グラフ処理関連製品を黙々と開発し続ける謎の開発者集団TinkerPopがリリースしたグラフクエリ言語(正確には、スクリプト言語的にグラフクエリを行うためのフレームワークって感じ)。
夜に食べ物を与えてはならず、水を掛けてはいけないアレが名前とキャラクターのモチーフのようだ。

事象

VertexとEdgeをいくらか作成するようなGremlinスクリプトを流すと、Vertexはきちんと増えているんだけど、Edgeの数(g.E.count()の結果)が0と出る。またg.Eの結果がなにも帰ってこない。
公式サイトから落とせるバイナリのバージョンがまだrcなのでバグなのか!?とか、
もしやVertexとEdgeでパーミッションが別で、Edgeの書き込み権限だけないのか!?とか、
いろいろ想像と調査をめぐらした結果、ずばりの事象についてGitHubのWikiに書いてあることがわかった。

要約すると、OrientDBで、設定がデフォルトの状態で、propertyを含まないEdgeを追加した場合、
直接参照できない"LightWeightEdge"、つまり「見えないEdge」が作成されるというのである。

Edgeは追加されていないのではない。見えないだけなのだ。えぇー・・・。

もっと正確に言えば、Gremlinのg.Eから参照できないというだけで、たとえばg.V.outEとかやると、g.Eに期待する結果と同じものが取得できたりする。

回避策

この状況を回避するためには、「見えないEdge」を作ってくれるおせっかいモードを以下のようにオフにすればよい。
g.setUseLightweightEdges(false)

これはaddEdgeするとき等、書き込む場合に効く設定なので、すでに「見えないEdge」を作ってしまった状態でこれを実行しても見えるようにはならない。
この設定を入れた状態でaddEdgeをすると、propertyが空でもg.Eで参照できるEdgeができるというわけだ。
また、この設定は現在のセッションにだけ有効なので、気になる場合には
g = new OrientGraph(...)
g.setUseLightweightEdges(false)

のようにGraphインスタンスの生成とセットにしておくと良いかもしれない。
ただし、propertyのないEdgeを大量に作成するようなスクリプトを流す場合は、この設定は入れないほうが速い。
でもそうすると作成されるのはLightWeightEdgeになっちゃうから痛し痒しである。


以上。なかなかやらかしてくれるわい。

0 件のコメント:

コメントを投稿