1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Neo4j をDockerで立ち上げてグラフDBを触ってみる

1
Last updated at Posted at 2026-03-22

Neo4j をDockerで立ち上げてグラフDBを触ってみる

はじめに

グラフデータベース Neo4j を Docker でローカルに立ち上げ、基本的なデータ操作を試してみます。


Neo4j とは

Neo4j はグラフデータベースです。データを**ノード(節点)リレーションシップ(辺)**で表現します。

(Alice)-[:KNOWS]->(Bob)-[:WORKS_AT]->(Acme Corp)
  ↑ノード   ↑リレーションシップ    ↑ノード
概念 説明
ノード エンティティ(人、会社、スキルなど)
リレーションシップ ノード間の関係(向きがある)
プロパティ ノード/リレーションシップのキーバリューデータ
ラベル ノードの種類(:Person, :Company など)

クエリ言語は Cypher を使います。SQL に相当する独自言語で、グラフのパターンを視覚的に表現できます。


環境構築

docker-compose.yml を作成

services:
  neo4j:
    image: neo4j:latest
    container_name: neo4j
    ports:
      - "7474:7474"  # Browser UI
      - "7687:7687"  # Bolt protocol
    environment:
      - NEO4J_AUTH=neo4j/password123
      - NEO4J_PLUGINS=["graph-data-science"]
    volumes:
      - neo4j_data:/data
      - neo4j_logs:/logs

volumes:
  neo4j_data:
  neo4j_logs:

NEO4J_PLUGINS を指定すると、起動時に GDS(Graph Data Science)プラグインが自動でインストールされます。GDS は Louvain 法や PageRank などのグラフアルゴリズムを提供するプラグインで、グラフ分析を行う際に必要になります。

起動

docker compose up -d

ブラウザUIにアクセス

http://localhost:7474 にアクセスして以下でログインします。

  • ユーザー名: neo4j
  • パスワード: password123

基本操作: ノードとリレーションシップの作成

Neo4j ブラウザ上部のクエリエディタに入力して Cmd+Enter で実行します。

① ノードを作成する

CREATE (alice:Person {name: "Alice", age: 30})
CREATE (bob:Person {name: "Bob", age: 25})
CREATE (carol:Person {name: "Carol", age: 35})
CREATE (acme:Company {name: "Acme Corp", industry: "Tech"})
CREATE (globex:Company {name: "Globex", industry: "Finance"})
CREATE (s1:Skill {name: "Python"})
CREATE (s2:Skill {name: "Neo4j"})
CREATE (s3:Skill {name: "Machine Learning"})

② リレーションシップを作成する

MATCH で既存ノードを検索し、CREATE でリレーションシップを作ります。

MATCH (alice:Person {name: "Alice"}), (bob:Person {name: "Bob"})
CREATE (alice)-[:KNOWS]->(bob)

MATCH (alice:Person {name: "Alice"}), (carol:Person {name: "Carol"})
CREATE (alice)-[:KNOWS]->(carol)

MATCH (bob:Person {name: "Bob"}), (acme:Company {name: "Acme Corp"})
CREATE (bob)-[:WORKS_AT {since: 2020}]->(acme)

MATCH (carol:Person {name: "Carol"}), (globex:Company {name: "Globex"})
CREATE (carol)-[:WORKS_AT {since: 2022}]->(globex)

MATCH (alice:Person {name: "Alice"}), (s1:Skill {name: "Python"})
CREATE (alice)-[:HAS_SKILL]->(s1)

MATCH (alice:Person {name: "Alice"}), (s2:Skill {name: "Neo4j"})
CREATE (alice)-[:HAS_SKILL]->(s2)

MATCH (bob:Person {name: "Bob"}), (s3:Skill {name: "Machine Learning"})
CREATE (bob)-[:HAS_SKILL]->(s3)

③ 全ノードとリレーションシップを確認する

MATCH (n)-[r]->(m) RETURN n, r, m

MATCH (n) RETURN n はノードのみ返すためグラフ表示になりません。リレーションシップも含めるには (n)-[r]->(m) の形式で取得します。

グラフビューで以下のような構造が表示されれば成功です。

(Alice) --[:KNOWS]--> (Bob) --[:WORKS_AT]--> (Acme Corp)
   |                    |
   |              [:HAS_SKILL]
   |                    |
[:KNOWS]         (Machine Learning)
   |
(Carol) --[:WORKS_AT]--> (Globex)

(Alice) --[:HAS_SKILL]--> (Python)
(Alice) --[:HAS_SKILL]--> (Neo4j)

プロパティの更新・削除

SET: プロパティを追加・更新する

MATCH (a:Person {name: "Alice"})
SET a.email = "alice@example.com", a.age = 31
RETURN a

REMOVE: プロパティを削除する

MATCH (a:Person {name: "Alice"})
REMOVE a.email
RETURN a

ラベルの追加・削除

// ラベルを追加
MATCH (a:Person {name: "Alice"})
SET a:Admin

// ラベルを削除
MATCH (a:Person {name: "Alice"})
REMOVE a:Admin

パターンマッチング

特定ノードを取得する

MATCH (n:Person {name: "Alice"})
RETURN n

リレーションシップをたどる(友人を取得)

MATCH (a:Person {name: "Alice"})-[:KNOWS]->(friend)
RETURN friend.name

友人の友人を取得

MATCH (a:Person {name: "Alice"})-[:KNOWS]->(friend)-[:KNOWS]->(fof)
RETURN fof.name

今回のデータでは Bob・Carol から先に :KNOWS を作っていないため0件になります。以下を追加すると確認できます:

MATCH (bob:Person {name: "Bob"}), (carol:Person {name: "Carol"})
CREATE (bob)-[:KNOWS]->(carol)

複数パターンを組み合わせる(友人が働いている会社)

MATCH (a:Person {name: "Alice"})-[:KNOWS]->(friend)-[:WORKS_AT]->(company)
RETURN friend.name, company.name

絞り込み・集計・並び替え

WHERE で条件を絞り込む

MATCH (n:Person)
WHERE n.age >= 30
RETURN n.name, n.age

ORDER BY と LIMIT

MATCH (n:Person)
RETURN n.name, n.age
ORDER BY n.age DESC
LIMIT 2

COUNT / AVG などの集計

MATCH (n:Person)
RETURN count(n) AS total, avg(n.age) AS avg_age

ラベルごとのノード数

MATCH (n)
RETURN labels(n) AS label, count(n) AS count

MATCH の挙動について

MATCH は SQL の SELECT ... FROM ... WHERE に相当し、パターンに一致するノードを検索します。

重要: MATCH が0件の場合、後続の CREATE も実行されません。クエリ全体がスキップされます。

// alice が存在しない場合、CREATE は実行されない
MATCH (alice:Person {name: "存在しない"})
CREATE (alice)-[:KNOWS]->(:Person {name: "Ghost"})
// → 0 nodes created

MATCHMERGE の違いは以下の通りです:

コマンド 動作
MATCH 一致するものを検索。なければスキップ
MERGE 一致するものを検索。なければ作成

パス探索

グラフDBの強みの1つが、ノード間の経路を効率よく探索できることです。

shortestPath で最短経路を取得

MATCH (a:Person {name: "Alice"}), (acme:Company {name: "Acme Corp"}),
      p = shortestPath((a)-[*]-(acme))
RETURN p, length(p) AS hops

[*] はリレーションシップの種類を問わず全てたどることを意味します。今回のデータでは以下の経路が返ります:

(Alice) -[:KNOWS]-> (Bob) -[:WORKS_AT]-> (Acme Corp)
  ↑ 1ホップ目               ↑ 2ホップ目

allShortestPaths で全最短経路を取得

MATCH (a:Person {name: "Alice"}), (acme:Company {name: "Acme Corp"}),
      p = allShortestPaths((a)-[*]-(acme))
RETURN p

同じ長さの最短経路が複数存在する場合、全件返します。shortestPath は1件のみ返す点が異なります。


可変長パス(k-hop探索)

[*1..N] の形式で「最大Nホップ先まで探索する」クエリを書けます。

-- 12ホップで繋がるノードを全て取得
MATCH (a:Person {name: "Alice"})-[*1..2]->(n)
RETURN DISTINCT n
-- ホップ数も一緒に確認
MATCH p = (a:Person {name: "Alice"})-[*1..3]->(n)
RETURN n, length(p) AS hops
ORDER BY hops

今回のデータでは Alice から到達できるのは最大2ホップまでです:

ホップ数 到達できるノード
1ホップ Bob, Carol, Python, Neo4j
2ホップ Acme Corp, Globex, Machine Learning
3ホップ 存在しない(Bob・Carol の先にリレーションシップがないため)

可変長パスは、特定ノードの周辺情報を一定のホップ数内で収集する際に便利なパターンです。


HTTP API でも操作できる

curl を使って外部から操作することも可能です:

curl -X POST http://localhost:7474/db/neo4j/tx/commit \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -u neo4j:password123 \
  -d '{"statements": [{"statement": "MATCH (n) RETURN n LIMIT 5"}]}'

まとめ

  • Neo4j は Docker で簡単にローカル起動できる
  • データはノードとリレーションシップで表現し、CREATE で作成する
  • MATCH でパターン検索、SET/REMOVE でプロパティを更新・削除する
  • MATCH が0件だと後続の CREATE も実行されない点に注意
  • WHEREORDER BY・集計関数でデータを柔軟に絞り込める
  • shortestPath() でノード間の最短経路を取得できる
  • [*1..N] の可変長パスで任意のホップ数まで探索できる
1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?