Amazon Neptuneで始める初めてのグラフDB② Gremlinを用いたグラフデータの基本操作

記事タイトルとURLをコピーする

こんにちは。
DevOpsが好きなアプリケーションサービス部の兼安です。

本記事は「Amazon Neptuneで始める初めてのグラフDB」というテーマの連載記事の2回目です。

本連載記事の目標

  • Amazon Neptuneに対する基本的な操作・認証・運用方法を習得する
  • Amazon Neptuneの全文検索を実装する

第2回目の目標

  • Amazon Neptune上のプロパティグラフに対してGremlinでデータ操作する基本構文を押さえる

Gremlinとは

本連載記事ではグラフDBのモデルにプロパティグラフを使用しています。
Gremlinはこのプロパティグラフを操作するクエリ言語です。
Gremlinは、Apache TinkerPopプロジェクトの一部として提供されているグラフデータベース用のクエリ言語で、グラフデータベース上で頂点(Vertex)やエッジ(Edge)を操作するために使用され、プロパティグラフモデルに基づいて、グラフデータの照会、挿入、更新、削除などの操作を行うことができます。

tinkerpop.apache.org

プロパティグラフを操作するクエリ言語はGremlinの他にopenCypherがあります。
AWS公式ページの記載もGremlinの方が先なので、2024年9月現在だとプロパティグラフのクエリ言語はGremlinがメジャーのようです。

docs.aws.amazon.com

Note You can access property graph data in Neptune using both Gremlin and openCypher, but not using SPARQL. Similarly, you can only access RDF data >using SPARQL, not Gremlin or openCypher.

プロパティグラフの用語

Gremlinのクエリに触れる前に、プロパティグラフの用語を整理しておきましょう。
基本的な用語をまとめてみました。
プロパティグラフの用語には、複数の呼称が存在するものがあります。
例えば、頂点/ノードはどちらも同じものを指します。
本記事ではクエリにGremlinを使うので、Gremlinのクエリに出てくる呼称に統一して書いていきます。
頂点/ノードは、GremlinではVertexと表現されるので、これを翻訳した頂点の方で統一します。

用語 用語
(日本語)
説明
Vertex (V) 頂点 エンティティを表す。例: 人、場所、物など。
Edge (E) エッジ 2つの頂点間の関係を表す。例: 「友人」「購入」「関連」など。
Property プロパティ 頂点やエッジに付与されるキーと値のペア。例: 名前、年齢、色など。
Label ラベル 頂点やエッジの種類を識別するための文字列。例: person, knows, product など。

Gremlinを用いたグラフデータの基本操作

Gremlinのクエリは、gremlinpythonライブラリを用いてPythonから実行します。

頂点の登録

g.addV("person").property("name", "justin").iterate()

addV()VはVertex(頂点)の略です。
addV()の引数はラベルで、頂点の種類を示します。
property()で頂点に対する属性を付与します。

このGremlinを用いたグラフデータ操作の一連のステップをトラバーサルと呼びます。
Gremlinのトラバーサルにおいて、データベースの状態に影響を与える操作を副作用があると表現します。
iterate()はクエリの内容をNeptuneに送信するのに必要な関数で、これがないとクエリを書いても送信されないのでトラバーサルは評価されずNeptuneに反映されません。

Gremlinには、iterate() のようにクエリの内容を送信するためのメソッドが複数存在します。

docs.aws.amazon.com

以下のメソッドは Neptune DB インスタンスにクエリを送信します。 toList() toSet() next() nextTraverser() iterate()

登録した結果を確認

登録した結果を確認します。
初回のため、すべての頂点を取得して確認してみます。

all_vertices = g.V().valueMap(True).toList()
print("All Vertices:", all_vertices)

toList()でクエリの実行結果をリスト化しています。
valueMap()は頂点やエッジのプロパティとその値を辞書形式で取得するための関数です。
valueMap(False)または、valueMap()を指定しないと頂点やエッジのオブジェクト情報やidが表示されますが、個別のプロパティ値(例えばnameやageなど)は出力されません。

頂点の登録と確認のPythonコード

頂点の登録と確認のPythonコードを一通り書くと以下のようになります。 次の2ステップをJupyter Notebookで実行します。

!pip install gremlinpython

Jupyter Notebookを使わず、通常のシェルコマンドとして実行する場合は、!pip!は不要です。

from gremlin_python import statics
from gremlin_python.structure.graph import Graph
from gremlin_python.process.graph_traversal import __
from gremlin_python.process.strategies import *
from gremlin_python.driver.driver_remote_connection import DriverRemoteConnection
from gremlin_python.driver.aiohttp.transport import AiohttpTransport
from gremlin_python.process.traversal import *

import os

port = 8182
server = "{Neptuneのエンドポイント}"
    
endpoint = f"wss://{server}:{port}/gremlin"
print(endpoint)

graph=Graph()

connection = None

try:
    connection = DriverRemoteConnection(endpoint, "g",
                                        transport_factory=lambda: AiohttpTransport(call_from_event_loop=True))

    g = graph.traversal().withRemote(connection)

    g.addV("person").property("name", "satoshi").iterate()

    # すべての頂点を確認する
    all_vertices = g.V().valueMap(True).toList()
    print("All Vertices:", all_vertices)

finally:
    if connection is not None:
        connection.close()

実行すると以下のように出力されます。

All Vertices: [{"name": ["satoshi"], <T.label: 4>: "person", <T.id: 1>: "b6c8dfb8-cb96-8798-cefd-6f98cb7343cd"}]

idを指定した頂点の登録

g.addV("person").property(T.id, "10").property("name", "satoshi").iterate()

プロパティグラフにおいて、idは特別な意味を持つプロパティであり、各頂点やエッジを一意に識別するための属性です。
idを使用することで、頂点やエッジを効率的に検索・更新・削除することができます。

上記のコードでは、頂点を登録する際にproperty(T.id, "10")によってidを指定しています。
通常、property()は(属性名, 属性値)の形式で指定しますが、idのような特別なプロパティを指定する場合は、固有の書き方をします。

T.idgremlinpythonでidを指定するための特別な構文です。
他のプログラミング言語やGremlinライブラリの場合は書き方が変わります。

idを指定した頂点の参照

idを指定して頂点を取得するには以下のように書きます。

vertex = g.V("10").valueMap(True).toList()
print("Vertex:", vertex)

頂点の更新

g.V()で頂点を取得できます。
引数にidを指定すればピンポイントで頂点を得られます。
これに対してproperty()で新たなプロパティを指定すればプロパティを追加できます。
property()addressを設定します。

g.V("10").property("address", "japan").iterate()
vertex = g.V("10").valueMap(True).toList()
print("Vertex:", vertex)
Vertex: [{"name": ["satoshi"], <T.label: 4>: "person", "address": ["japan"], <T.id: 1>: "10"}]

ここから、property()addressを上書きを試みます。

g.V("10").property("address", "hiroshima").iterate()
vertex = g.V("10").valueMap(True).toList()
print("Vertex:", vertex)
Vertex: [{"name": ["satoshi"], <T.label: 4>: "person", "address": ["hiroshima", "japan"], <T.id: 1>: "10"}]

プロパティの値が上書きされず、追加されました。
これは、property()のデフォルトの動きがプロパティ値の追加だからです。
プロパティ値の追加ではなく、更新をする場合は以下のように書きます。

from gremlin_python.process.traversal import Cardinality

g.V("10").property(Cardinality.single, "name", "satoshi256kbyte").iterate()
vertex = g.V("10").valueMap(True).toList()
print("Vertex:", vertex)
Vertex: [{"name": ["satoshi256kbyte"], <T.label: 4>: "person", "address": ["hiroshima", "japan"], <T.id: 1>: "10"}]

すべての頂点を削除する

以下のように書きます。
今は実験中なので、これが重宝します。

g.V().drop().iterate()

g.V()は引数で何も指定していないので、すべての頂点を選択します。
drop()は選択されたすべての頂点と、それに関連するエッジを削除します。
iterate()によりクエリを実行して変更を確定します。

次回に向けて

今回はここまでです。
次回はグラフデータの可視化を行うために、可視化ツールを導入します。

参考ページ

docs.aws.amazon.com

docs.aws.amazon.com

兼安 聡(執筆記事の一覧)

アプリケーションサービス部 DS3課所属
2025 Japan AWS Top Engineers (AI/ML Data Engineer)
2025 Japan AWS All Certifications Engineers
2025 AWS Community Builders
Certified ScrumMaster
PMP
広島在住です。今日も明日も修行中です。
X(旧Twitter)