Azure Cosmos DB では複数のデータベース API が提供されていますが、これまでは SQL API くらいしか使ったことがなかったので、以前から気になっていた Gremlin API を試してみました。
docs.microsoft.com
グラフデータベースとは
グラフデータベースは、「ノード」と「ノード間の関係を表すエッジ」で構成されるデータベースです。
代表的な事例としては、Facebook などの SNS で友達の友達を辿ったり、EC サイトで購入した商品と関連のある商品をレコメンドするケースがあります。
リレーショナルデータベースでも実現できますが、新しいデータの追加や修正が容易で、データ量が増えてもデータ間の関係を検索するスピードが速いことが特徴です。
Gremlin API とは
代表的なグラフデータベースの Neo4j は、グラフ構造のデータ処理を行うために Cypher というクエリ言語を使います。
グラフデータベースは Neo4j のほかにもあり、グラフデータベース毎にクエリ言語が異なる課題を解決するため、TinkerPop という Apache プロジェクトでグラフデータベースの操作を統一的に行えるようにする仕組みとして Gremlin が提供されています。
Azure Cosmos DB では、この Gremlin をサポートしており、ノードやエッジの作成、クエリ検索を行うことができます。
Gremlin では、次のような用語でグラフデータベースの構造を表現しています。
- Vertex・・・ノード
- Edge・・・エッジ
- Label・・・ノードの種類
- Property・・・ノードやエッジの属性
グラフデータベースを作成する
Azure Portal から Gremlin API を選択して Azure Cosmos DB を作成し、適当な名前で新しい Graph を作成します。Graph は、SQL API での Container に相当しますが、Partition key に /id を使うことができません。
空の Graph が作成され、Gremlin のクエリを実行できるようになります。g.V()
は、Graph の全てのデータを取得するクエリです。
グラフデータを登録する
Azure Portal のデータエクスプローラーを使って、グラフデータを登録していきます。
Vertex と Edge の登録は、Gremlin クエリの addV()
と addE()
を使います。
まずは、product
という label をもつ Vertex を登録します。property には id
や name
を設定します。
g.addV('product').property('id', '5toubun').property('name', '五等分の花嫁').property('released', 2019).property('pk', 'pk') g.addV('product').property('id', 'gochiusa').property('name', 'ご注文はうさぎですか?').property('released', 2014).property('pk', 'pk') g.addV('product').property('id', 'yurucan').property('name', 'ゆるキャン△').property('released', 2018).property('pk', 'pk')
つぎに、person
という label をもつ Vertex を登録します。
g.addV('person').property('id', 'kana').property('name', '花澤香菜').property('gender', 'female').property('pk', 'pk') g.addV('person').property('id', 'ayana').property('name', '竹達彩奈').property('gender', 'female').property('pk', 'pk') g.addV('person').property('id', 'miku').property('name', '伊藤美来').property('gender', 'female').property('pk', 'pk') g.addV('person').property('id', 'ayane').property('name', '佐倉綾音').property('gender', 'female').property('pk', 'pk') g.addV('person').property('id', 'inori').property('name', '水瀬いのり').property('gender', 'female').property('pk', 'pk') g.addV('person').property('id', 'risa').property('name', '種田梨沙').property('gender', 'female').property('pk', 'pk') g.addV('person').property('id', 'nao').property('name', ' 東山奈央').property('gender', 'female').property('pk', 'pk') g.addV('person').property('id', 'yumiri').property('name', ' 花守ゆみり').property('gender', 'female').property('pk', 'pk')
最後に、acted-in
という Edge を登録し、product
と person
の関係を表します。
g.V('kana').addE('acted-in').to(g.V('5toubun')) g.V('ayana').addE('acted-in').to(g.V('5toubun')) g.V('miku').addE('acted-in').to(g.V('5toubun')) g.V('ayane').addE('acted-in').to(g.V('5toubun')) g.V('inori').addE('acted-in').to(g.V('5toubun')) g.V('ayane').addE('acted-in').to(g.V('gochiusa')) g.V('inori').addE('acted-in').to(g.V('gochiusa')) g.V('risa').addE('acted-in').to(g.V('gochiusa')) g.V('nao').addE('acted-in').to(g.V('yurucan')) g.V('yumiri').addE('acted-in').to(g.V('yurucan'))
登録されたグラフデータの一覧を表示します。見栄えをよくするため、id ではなく name を表示するようにグラフのスタイルを変更しています。
グラフデータを検索する
Gremlin クエリで Vertex と Edge を辿っていく場合、inE() / outE()
と inV() / outV()
を使います。Edge の方向によって in と out を使い分け、Vertex の種類を hasLabel()
で指定するのが基本的な使い方です。
五等分の花嫁に出演している声優を検索すると、5人の声優を取得できます。
g.V('5toubun').inE('acted-in').outV().hasLabel('person')
水瀬いのりが出演している作品を検索すると、2つの作品を取得できます。
g.V('inori').outE('acted-in').inV().hasLabel('product')
水瀬いのりが出演している作品に出演している声優を検索すると、6人の声優を取得できます。
g.V('inori').outE('acted-in').inV().hasLabel('product').inE('acted-in').outV().hasLabel('person')
まとめ
Azure Cosmos DB の Gremlin API を試してみました。Azure Portal のデータエクスプローラーで視覚化されるので、直感的にクエリを実行できます。
グラフのデータ構造を管理する場合には、リレーショナルデータベースで再帰クエリを使うよりも速いので、ユースケースがハマれば使ってみたいと感じました。
ただし、Web アプリケーションに検索したグラフを組み込むとなると、Cosmos DB のほかに可視化する手段が必要になります。
Likurious Enterprise を試してみたので、こちらの記事も参照してください。
gooner.hateblo.jp