はじめの一歩
この章では、Neo4j を使ってグラフDB を実際に体験します。環境構築から Cypher の基本操作まで、RDB 経験者が迷わず進められるように SQL との対比を交えて解説します。
環境の準備
Neo4j を試す方法は3つあります。目的に応じて選んでください。
| 方法 | 特徴 | 推奨シーン |
|---|---|---|
| Neo4j Desktop | GUI アプリ。ローカルで完結 | じっくり学習したい(要アカウント登録) |
| Neo4j Aura Free | クラウド。インストール不要 | すぐに試したい(要アカウント登録) |
| Docker / Podman | コマンド1つで起動。アカウント不要 | 開発環境に慣れている |
Neo4j Desktop で始める
- neo4j.com/download から Neo4j Desktop をダウンロード(無料、要アカウント登録)
- インストーラーを実行し、起動
- 「New Project」→「Add Database」→「Local DBMS」を選択
- パスワードを設定して「Create」
- 「Start」でデータベースを起動
- 「Open」で Neo4j Browser が起動し、Cypher を入力できる画面が開く
Neo4j Browser はグラフを視覚的に表示できる組み込みツールです。ノードとエッジが図として表示されるので、データの関係を直感的に理解できます。RDB の管理ツール(pgAdmin や SQL Developer)に相当します。
Neo4j Aura で始める
- neo4j.com/cloud/aura-free にアクセス
- アカウントを作成し、「Create Free Instance」をクリック
- 生成された接続情報(パスワード)を控える
- 数分でインスタンスが起動し、ブラウザから Cypher を実行可能
Aura Free は容量制限(ノード数 20万、関係数 40万)がありますが、学習には十分です。
Docker(又は Podman)で始める
以下は Docker のコマンド例です。Podman でも docker を podman に読み替えればそのまま動作します。
# 永続化先のディレクトリを作成
mkdir -p ~/neo4j/{data,logs,conf}
# Neo4j を起動
# ポート 7474: Browser, 7687: Bolt
docker run -d \
--name neo4j \
-p 7474:7474 -p 7687:7687 \
-v ~/neo4j/data:/data \
-v ~/neo4j/logs:/logs \
-v ~/neo4j/conf:/conf \
-e NEO4J_AUTH=neo4j/password123 \
neo4j:latest
起動後、ブラウザで http://localhost:7474 にアクセスすると Neo4j Browser が開きます。
ボリュームの役割: -v ~/neo4j/data:/data でホスト側のディレクトリをマウントしているため、コンテナを停止・削除してもデータはそのまま残ります。/logs と /conf も永続化しておくと、ログの確認や設定変更がコンテナ再作成後も引き継がれます。
Cypher の基本
Cypher は Neo4j のクエリ言語で、SQL に似た宣言型の構文を持ちます。最大の特徴はグラフパターンを ASCII アートのように記述できることです。
基本構文の対比
| 操作 | SQL | Cypher |
|---|---|---|
| データ作成 | INSERT INTO | CREATE |
| データ検索 | SELECT ... FROM ... WHERE | MATCH ... WHERE ... RETURN |
| データ更新 | UPDATE ... SET | MATCH ... SET |
| データ削除 | DELETE FROM | MATCH ... DELETE |
| 条件指定 | WHERE | WHERE(同じ) |
| 並べ替え | ORDER BY | ORDER BY(同じ) |
| 件数制限 | LIMIT | LIMIT(同じ) |
パターン記法
Cypher の核心はパターン記法です。ノードを丸括弧 ()、エッジを角括弧と矢印 -[]-> で表現します。
// ノード
(p:Person {name: "Alice"})
// エッジ(方向あり)
(a)-[:KNOWS]->(b)
// パターンの組み合わせ
(a:Person)-[:WORKS_AT]->(c:Company {name: "Acme"})
データの作成
以下のサンプルデータを作成して、Cypher の基本操作を体験しましょう。「会社の従業員と部署」という RDB 経験者に馴染みのある題材を使います。
// 部署を作成
CREATE (dev:Department {name: "開発部", floor: 3})
CREATE (sales:Department {name: "営業部", floor: 5})
// 従業員を作成
CREATE (tanaka:Employee {name: "田中", age: 35, role: "リーダー"})
CREATE (suzuki:Employee {name: "鈴木", age: 28, role: "メンバー"})
CREATE (sato:Employee {name: "佐藤", age: 42, role: "部長"})
CREATE (yamada:Employee {name: "山田", age: 31, role: "メンバー"})
// 関係を作成
CREATE (tanaka)-[:BELONGS_TO {since: 2020}]->(dev)
CREATE (suzuki)-[:BELONGS_TO {since: 2023}]->(dev)
CREATE (sato)-[:BELONGS_TO {since: 2015}]->(dev)
CREATE (yamada)-[:BELONGS_TO {since: 2021}]->(sales)
// 上司-部下の関係
CREATE (tanaka)-[:REPORTS_TO]->(sato)
CREATE (suzuki)-[:REPORTS_TO]->(tanaka)
// 同僚関係(プロジェクトでの協業)
CREATE (tanaka)-[:COLLABORATES {project: "システムA"}]->(yamada)
SQL との違い: RDB ではまず CREATE TABLE でスキーマを定義し、その後 INSERT でデータを投入します。Cypher ではスキーマ定義なしにいきなりデータを作成できます。ラベル(:Employee)とプロパティ({name: "田中"})はデータ投入時に決まります。
データの検索
基本的な検索
// 全従業員を取得(SQL: SELECT * FROM employees)
MATCH (e:Employee)
RETURN e.name, e.age, e.role
// 条件付き検索(SQL: SELECT * FROM employees WHERE age > 30)
MATCH (e:Employee)
WHERE e.age > 30
RETURN e.name, e.age
関係をたどる検索
// 開発部に所属する従業員(SQL: SELECT ... FROM employees JOIN departments ...)
MATCH (e:Employee)-[:BELONGS_TO]->(d:Department {name: "開発部"})
RETURN e.name, e.role
// 田中の上司を探す
MATCH (e:Employee {name: "田中"})-[:REPORTS_TO]->(boss)
RETURN boss.name, boss.role
// 佐藤の部下を全て探す(直属 + 間接)
MATCH (boss:Employee {name: "佐藤"})<-[:REPORTS_TO*1..3]-(sub)
RETURN sub.name
集計
// 部署ごとの人数(SQL: SELECT dept, COUNT(*) GROUP BY dept)
MATCH (e:Employee)-[:BELONGS_TO]->(d:Department)
RETURN d.name, count(e) AS members
ORDER BY members DESC
データの更新
// プロパティの更新(SQL: UPDATE employees SET age = 36 WHERE name = '田中')
MATCH (e:Employee {name: "田中"})
SET e.age = 36
// プロパティの追加(スキーマ変更不要!)
MATCH (e:Employee {name: "田中"})
SET e.email = "[email protected]"
// ラベルの追加(RDB にはない概念)
MATCH (e:Employee {name: "佐藤"})
SET e:Manager
// 新しい関係の追加
MATCH (a:Employee {name: "鈴木"}), (b:Employee {name: "山田"})
CREATE (a)-[:COLLABORATES {project: "システムB"}]->(b)
ALTER TABLE が不要: RDB で列を追加するには ALTER TABLE ADD COLUMN が必要ですが、Cypher では SET で新しいプロパティをいきなり追加できます。既存のノードに影響はありません。
データの削除
// 関係の削除
MATCH (e:Employee {name: "田中"})-[r:COLLABORATES]->(other)
DELETE r
// ノードの削除(関係があるノードは先に関係を削除する必要がある)
MATCH (e:Employee {name: "山田"})-[r]-()
DELETE r, e
// DETACH DELETE で関係ごとまとめて削除
MATCH (e:Employee {name: "山田"})
DETACH DELETE e
注意: RDB の ON DELETE CASCADE のような自動連鎖削除はありません。関係を持つノードを削除するには DETACH DELETE を使うか、先に関係を削除する必要があります。
RDB 概念との対応表
RDB の知識をグラフDB に活かすための対応表です。
| RDB の概念 | グラフDB の対応概念 | 備考 |
|---|---|---|
| テーブル | ラベル | :Employee, :Department |
| 行(レコード) | ノード | プロパティの集合 |
| 列(カラム) | プロパティ | スキーマレスで柔軟 |
| 主キー | 内部ID(自動)+ ユニーク制約 | CREATE CONSTRAINT で設定 |
| 外部キー | エッジ | 直接参照。JOIN 不要 |
| 中間テーブル | エッジ(プロパティ付き) | 多対多も自然に表現 |
| JOIN | パターンマッチ | MATCH (a)-[r]->(b) |
| 再帰CTE | 可変長パス | [:REL*1..5] |
| CREATE TABLE | 不要 | データ作成時に暗黙的に定義 |
| ALTER TABLE | 不要 | SET で随時追加 |
| INDEX | CREATE INDEX | プロパティにインデックスを設定可能 |
| UNIQUE 制約 | CREATE CONSTRAINT ... IS UNIQUE | Neo4j でサポート |
ラベル名・エッジタイプ名のリネームはできない:
「CREATE TABLE が不要」と聞くと自由度が高く感じますが、一度付けたラベル名(例: :Employee)やエッジタイプ名(例: :BELONGS_TO)を一括リネームする機能は Neo4j には存在しません。変更するには全対象ノードに対して「新ラベルを付与 → 旧ラベルを削除」を自分で実行する必要があります。
// ラベルを Employee → Staff に変更する場合
MATCH (n:Employee)
SET n:Staff
REMOVE n:Employee
RDB の ALTER TABLE RENAME に相当する操作が無いため、ラベル名やエッジタイプ名は最初の設計時に慎重に決めましょう。スキーマレスだからといって「後から何でも変えられる」わけではない点は、RDB 経験者が特に注意すべきポイントです。
練習問題
上記のサンプルデータを使って、以下のクエリを Cypher で書いてみましょう。
- 30歳以上の従業員の名前と年齢を取得する
- 開発部に所属する従業員の名前を取得する
- 田中が協業しているプロジェクト名と相手の名前を取得する
- 佐藤から2ホップ以内の部下全員の名前を取得する
- 全従業員に
companyプロパティとして"ACME"を追加する
解答例
// 1.
MATCH (e:Employee) WHERE e.age >= 30 RETURN e.name, e.age
// 2.
MATCH (e:Employee)-[:BELONGS_TO]->(d:Department {name:"開発部"}) RETURN e.name
// 3.
MATCH (e:Employee {name:"田中"})-[c:COLLABORATES]->(other)
RETURN c.project, other.name
// 4.
MATCH (boss:Employee {name:"佐藤"})<-[:REPORTS_TO*1..2]-(sub)
RETURN sub.name
// 5.
MATCH (e:Employee) SET e.company = "ACME"
Java からのアクセス
RDB に JDBC ドライバがあるように、Neo4j にも公式の Java ドライバがあります。 接続には Bolt プロトコル(ポート 7687)を使います。JDBC Type 4 ドライバと同様に純 Java 実装で、ネイティブライブラリは不要です。
ドライバの比較
| 観点 | JDBC(RDB) | Neo4j Java Driver |
|---|---|---|
| 接続文字列 | jdbc:postgresql://host:5432/db | bolt://host:7687 |
| クエリ言語 | SQL | Cypher |
| 結果の型 | ResultSet | Result / Record |
| トランザクション | Connection.setAutoCommit() | Session.executeWrite() |
| コネクション管理 | DataSource / コネクションプール | Driver(内蔵プール) |
Maven 依存
<dependency>
<groupId>org.neo4j.driver</groupId>
<artifactId>neo4j-java-driver</artifactId>
<version>5.27.0</version>
</dependency>
コード例: 接続・作成・検索
import org.neo4j.driver.*;
public class Neo4jExample {
public static void main(String[] args) {
// ドライバ生成(内蔵コネクションプール付き)
// RDB の DataSource に相当
try (Driver driver = GraphDatabase.driver(
"bolt://localhost:7687",
AuthTokens.basic("neo4j", "password123"))) {
// セッション ≒ JDBC の Connection
try (Session session = driver.session()) {
// 書き込みトランザクション(ノードと関係を作成)
session.executeWrite(tx -> {
tx.run("""
MERGE (a:Person {name: $name1})
MERGE (b:Person {name: $name2})
MERGE (a)-[:KNOWS {since: $since}]->(b)
""",
Values.parameters(
"name1", "Alice",
"name2", "Bob",
"since", 2024));
return null;
});
// 読み取りトランザクション(検索)
session.executeRead(tx -> {
Result result = tx.run("""
MATCH (a:Person {name: $name})-[:KNOWS]->(friend)
RETURN friend.name AS friendName
""",
Values.parameters("name", "Alice"));
// RDB の ResultSet.next() に相当
while (result.hasNext()) {
Record record = result.next();
System.out.println(record.get("friendName").asString());
}
return null;
});
}
}
}
}
JDBC との類似点: Driver → Session → Transaction → Result という階層は、JDBC の DataSource → Connection → Statement → ResultSet とほぼ対応しています。また、$name はJDBC のプレースホルダ ? に相当するパラメータで、SQL インジェクションと同様のインジェクション対策として必ずパラメータ化して使います。
その他の言語: Neo4j は Java 以外にも Python(neo4j パッケージ)、JavaScript/TypeScript(neo4j-driver)、.NET、Go の公式ドライバを提供しています。いずれも Bolt プロトコルで接続し、API の構造は Java 版と同様です。
次のステップ
このガイドで基礎を学んだら、以下のリソースでさらに理解を深められます。
- Neo4j GraphAcademy — Neo4j 公式の無料学習コース。Cypher を体系的に学べる
- Neo4j Sandbox — テーマ別のサンプルデータセット(映画、SNS、不正検知など)で実践
- 「Graph Databases」(O'Reilly) — グラフDB の定番書籍。概念から実装まで
- openCypher.org — Cypher の言語仕様とリファレンス
- GQL 標準仕様 — ISO/IEC 39075 の概要と今後の展望
RDB 経験者へのアドバイス: グラフDB は RDB を否定するものではなく、補完するものです。まずは「RDB で書くと再帰CTE や多段 JOIN になって辛い」と感じた場面を思い出してください。そこがグラフDB の出番です。既存の RDB はそのまま活かしつつ、関係探索の部分だけグラフDB を導入するのが最も堅実なアプローチです。