using-graph-databases について
エンティティ間の関係や探索が重要なアプリケーション向けに、グラフデータベースの選定と実装を案内するスキルです。製品選定、モデリング、クエリ、最適化を扱います。
主な機能
- 01グラフデータベースの選定
- 02ノードとリレーションのモデリング
- 03Cypher クエリパターンの活用
- 04スキーマと探索の検証
- 05インデックスとキャッシュの最適化
活用シーン
- 01ソーシャル関係のクエリ構築
- 02AI/RAG にグラフコンテキストを追加
- 03レコメンドエンジンの作成
- 04つながりを使った不正検知
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ ancoleman/ ai-design-components --skill using-graph-databasesインストール後、Claude Code で/using-graph-databasesを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
outputs.yamlexamples/knowledge-graph/hybrid_vector_graph.pyexamples/social-graph/schema.cypherexamples/social-graph/python-neo4j/main.pyexamples/social-graph/typescript-neo4j/index.tsreferences/arangodb.mdcypher-patterns.mdgraph-modeling.mdneo4j.mdscripts/validate_graph_schema.py詳細
グラフデータベース
目的
このスキルでは、エンティティ間の関係が重要な役割を果たすアプリケーション向けに、グラフデータベースの選定と実装について説明します。外部キーと結合によって関係をモデル化するリレーショナルデータベースとは異なり、グラフデータベースは接続をプロパティとしてネイティブに表現できるため、トラバーサルを多用するクエリを効率的に実行できます。
このスキルを使う場面
次のような場合はグラフデータベースを使用します。
- 関係を深くたどる場合(4 ホップ以上): 「友達の友達の友達」
- 関係が可変または進化する場合:スキーマを変更しても、既存のクエリに影響しません
- 経路検索:最短経路、ネットワーク分析、依存関係の連鎖
- パターンマッチング:不正検出、レコメンデーションエンジン、アクセス制御
次のような場合はグラフデータベースを使用しないでください:
- スキーマが固定で、浅い結合(2~3 テーブル)が中心の場合 → PostgreSQL を使用
- 主に集計や分析を行う場合 → カラム型データベースを使用
- キーと値の検索だけを行う場合 → Redis/DynamoDB を使用
すばやく選定するための指針
DATA CHARACTERISTICS?
├── Fixed schema, shallow joins (≤3 hops)
│ └─ PostgreSQL (relational)
│
├── Already on PostgreSQL + simple graphs
│ └─ Apache AGE (PostgreSQL extension)
│
├── Deep traversals (4+ hops) + general purpose
│ └─ Neo4j (battle-tested, largest ecosystem)
│
├── Multi-model (documents + graph)
│ └─ ArangoDB
│
├── AWS-native, serverless
│ └─ Amazon Neptune
│
└── Real-time streaming, in-memory
└─ Memgraph
基本概念
プロパティグラフモデル
グラフデータベースでは、データを次のように保存します。
- ノード(頂点):ラベルとプロパティを持つエンティティ
- リレーションシップ(エッジ):プロパティを持つ型付きの接続
- プロパティ:ノードとリレーションシップ上のキーと値のペア
(Person {name: "Alice", age: 28})-[:FRIEND {since: "2020-01-15"}]->(Person {name: "Bob"})
クエリ言語
| 言語 | データベース | 読みやすさ | 最適な用途 |
|---|---|---|---|
| Cypher | Neo4j、Memgraph、AGE | ⭐⭐⭐⭐⭐ SQL に類似 | 汎用 |
| Gremlin | Neptune、JanusGraph | ⭐⭐⭐ 関数型 | 複数のデータベースに対応 |
| AQL | ArangoDB | ⭐⭐⭐⭐ SQL に類似 | マルチモデル |
| SPARQL | Neptune、RDF ストア | ⭐⭐⭐ W3C 標準 | セマンティック Web |
よく使う Cypher パターン
包括的な例については、references/cypher-patterns.md を参照してください。
パターン 1:基本的なマッチング
// Find all users at a company
MATCH (u:User)-[:WORKS_AT]->(c:Company {name: 'Acme Corp'})
RETURN u.name, u.title
パターン 2:可変長パス
// Find friends up to 3 degrees away
MATCH (u:User {name: 'Alice'})-[:FRIEND*1..3]->(friend)
WHERE u <> friend
RETURN DISTINCT friend.name
LIMIT 100
パターン 3:最短経路
// Find shortest connection between two users
MATCH path = shortestPath(
(a:User {name: 'Alice'})-[*]-(b:User {name: 'Bob'})
)
RETURN path, length(path) AS distance
パターン 4:レコメンデーション
// Collaborative filtering: Products liked by similar users
MATCH (u:User {id: $userId})-[:PURCHASED]->(p:Product)<-[:PURCHASED]-(similar)
MATCH (similar)-[:PURCHASED]->(rec:Product)
WHERE NOT exists((u)-[:PURCHASED]->(rec))
RETURN rec.name, count(*) AS score
ORDER BY score DESC
LIMIT 10
パターン 5:不正検出
// Detect circular money flows
MATCH path = (a:Account)-[:SENT*3..6]->(a)
WHERE all(r IN relationships(path) WHERE r.amount > 1000)
RETURN path, [r IN relationships(path) | r.amount] AS amounts
データベース選定ガイド
Neo4j(第一推奨)
用途:汎用グラフアプリケーション
強み:
- 最も成熟しており(2007 年)、最大規模のコミュニティ(開発者 200 万人以上)
- 65 種類以上のグラフアルゴリズム(GDS ライブラリ):PageRank、Louvain、Dijkstra
- 優れたツール:Neo4j Browser、Bloom の可視化機能
- Cypher を包括的にサポート
インストール:
# Python driver
pip install neo4j
# TypeScript driver
npm install neo4j-driver
# Rust driver
cargo add neo4rs
参照:references/neo4j.md
ArangoDB
用途:マルチモデルアプリケーション(ドキュメント+グラフ)
強み:
- ドキュメントとグラフを 1 つのデータベースに保存
- AQL でドキュメントクエリとグラフクエリを組み合わせられる
- リレーションシップに対応したスキーマの柔軟性
参照:references/arangodb.md
Apache AGE
用途:既存の PostgreSQL にグラフ機能を追加する場合
強み:
- PostgreSQL をグラフクエリに対応させる
- 新しいインフラストラクチャが不要
- リレーショナルデータとグラフデータの両方をクエリできる
参照:実装の詳細は examples/ を参照してください
Amazon Neptune
用途:AWS ネイティブのサーバーレスデプロイ
強み:
- フルマネージドで、自動スケーリングに対応
- Gremlin と SPARQL の両方をサポート
- AWS エコシステムと統合
グラフデータモデリングのパターン
包括的なパターンについては、references/graph-modeling.md を参照してください。
ベストプラクティス 1:リレーションシップを第一級の要素として扱う
アンチパターン(ノードのプロパティにリレーションシップを格納する):
// BAD
(:Person {name: 'Alice', friend_ids: ['b123', 'c456']})
パターン(リレーションシップを明示的に表現する):
// GOOD
(:Person {name: 'Alice'})-[:FRIEND]->(:Person {id: 'b123'})
(:Person {name: 'Alice'})-[:FRIEND]->(:Person {id: 'c456'})
ベストプラクティス 2:メタデータにはリレーションシップのプロパティを使う
// Track interaction details on relationships
(:Person)-[:FRIEND {
since: '2020-01-15',
strength: 0.85,
last_interaction: datetime()
}]->(:Person)
ベストプラクティス 3:パフォーマンスのためにトラバーサルの範囲を制限する
// SLOW: Unbounded traversal
MATCH (a)-[:FRIEND*]->(distant)
RETURN distant
// FAST: Bounded depth with index
MATCH (a)-[:FRIEND*1..4]->(distant)
WHERE distant.active = true
RETURN distant
LIMIT 100
ベストプラクティス 4:スーパーノードを避ける
問題:数千のリレーションシップを持つノードは、トラバーサルを遅くします。
解決策:中間集約ノード
// Instead of: (:User)-[:POSTED]->(:Post) [1M relationships]
// Use time partitioning:
(:User)-[:POSTED_IN]->(:Year {year: 2025})
-[:HAS_MONTH]->(:Month {month: 12})
-[:HAS_POST]->(:Post)
ユースケースの例
ソーシャルネットワーク
スキーマと実装については examples/social-graph/ を参照してください。
主な機能:
- 友達のおすすめ(友達の友達)
- 共通のつながり
- ニュースフィードの生成
- 影響力の指標
AI/RAG 向けナレッジグラフ
examples/knowledge-graph/ の統合例
主な機能:
- ベクトル検索とグラフ検索のハイブリッド
- エンティティ間の関係マッピング
- LLM プロンプト向けのコンテキスト拡張
- 意味的な関係のたどり
ベクトルデータベースとの統合:
# Step 1: Vector search in Qdrant/pgvector
vector_results = qdrant.search(collection="concepts", query_vector=embedding)
# Step 2: Expand with graph relationships
concept_ids = [r.id for r in vector_results]
graph_context = neo4j.run("""
MATCH (c:Concept) WHERE c.id IN $ids
MATCH (c)-[:RELATED_TO|IS_A*1..2]-(related)
RETURN c, related, relationships(path)
""", ids=concept_ids)
レコメンデーションエンジン
examples/social-graph/ の例
戦略:
- 協調フィルタリング:「Xを購入したユーザーはYも購入しています」
- コンテンツベース:「あなたの好みに似た商品」
- セッションベース:「最近閲覧したアイテム」
不正検出
examples/ でのパターン検出
検出パターン:
- 循環する資金の流れ
- アカウント間で共有されているデバイス
- 急速に連鎖するトランザクション
- 接続パターンの異常
パフォーマンスの最適化
詳細な最適化については、references/cypher-patterns.md を参照してください。
インデックス作成
// Single-property index
CREATE INDEX user_email FOR (u:User) ON (u.email)
// Composite index (Neo4j 5.x+)
CREATE INDEX user_name_location FOR (u:User) ON (u.name, u.location)
// Full-text search
CREATE FULLTEXT INDEX product_search FOR (p:Product) ON EACH [p.name, p.description]
高コストな集計のキャッシュ
// Materialize friend count as property
MATCH (u:User)-[:FRIEND]->(f)
WITH u, count(f) AS friendCount
SET u.friend_count = friendCount
// Query becomes instant
MATCH (u:User) WHERE u.friend_count > 100
RETURN u.name, u.friend_count
スケーリング戦略
| 規模 | 戦略 | 実装 |
|---|---|---|
| 垂直 | RAM/CPU を増強 | インメモリキャッシュ、より大規模なインスタンス |
| 水平(読み取り) | 読み取りレプリカ | Neo4j Cluster、ArangoDB Cluster |
| 水平(書き込み) | シャーディング | ArangoDB SmartGraphs、JanusGraph |
| キャッシュ | アプリケーションレベルのキャッシュ | 頻繁にアクセスする処理経路に Redis |
言語との統合
Python(Neo4j)
examples/social-graph/python-neo4j/ に完全な実装例があります。
from neo4j import GraphDatabase
class GraphDB:
def __init__(self, uri: str, user: str, password: str):
self.driver = GraphDatabase.driver(uri, auth=(user, password))
def find_friends_of_friends(self, user_id: str, max_depth: int = 2):
query = """
MATCH (u:User {id: $userId})-[:FRIEND*1..$maxDepth]->(fof)
WHERE u <> fof
RETURN DISTINCT fof.id, fof.name
LIMIT 100
"""
with self.driver.session() as session:
result = session.run(query, userId=user_id, maxDepth=max_depth)
return [dict(record) for record in result]
# Usage
db = GraphDB("bolt://localhost:7687", "neo4j", "password")
friends = db.find_friends_of_friends("u123", max_depth=3)
TypeScript(Neo4j)
examples/social-graph/typescript-neo4j/ に完全な実装例があります。
import neo4j, { Driver } from 'neo4j-driver'
class Neo4jService {
private driver: Driver
constructor(uri: string, username: string, password: string) {
this.driver = neo4j.driver(uri, neo4j.auth.basic(username, password))
}
async findFriendsOfFriends(userId: string, maxDepth: number = 2) {
const session = this.driver.session()
try {
const result = await session.run(
`MATCH (u:User {id: $userId})-[:FRIEND*1..$maxDepth]->(fof)
WHERE u <> fof
RETURN DISTINCT fof.id, fof.name
LIMIT 100`,
{ userId, maxDepth }
)
return result.records.map(r => r.toObject())
} finally {
await session.close()
}
}
}
Go(ArangoDB)
import (
"github.com/arangodb/go-driver"
"github.com/arangodb/go-driver/http"
)
func findFriendsOfFriends(db driver.Database, userId string, maxDepth int) ([]User, error) {
query := `
FOR vertex, edge, path IN 1..@maxDepth OUTBOUND @startVertex GRAPH 'socialGraph'
FILTER vertex._id != @startVertex
RETURN DISTINCT vertex
LIMIT 100
`
cursor, err := db.Query(ctx, query, map[string]interface{}{
"startVertex": userId,
"maxDepth": maxDepth,
})
// Handle results...
}
スキーマの検証
scripts/validate_graph_schema.py を使用して、以下を確認します:
- 上限のないトラバーサル(深さ制限の欠落)
- 頻繁にクエリされるプロパティに対するインデックスの欠落
- スーパーノード(過剰な数のリレーションシップを持つノード)
- リレーションシップのプロパティの一貫性
検証の実行:
python scripts/validate_graph_schema.py --database neo4j://localhost:7687
他のスキルとの統合
databases-vector との連携(ハイブリッド検索)
ベクトル類似度とグラフコンテキストを組み合わせて、AI/RAG アプリケーションを構築します。
examples/knowledge-graph/ を参照してください。
search-filter との連携
関係に基づくクエリを実装します:「接続が3段階以内にあるすべてのユーザーを検索する」
ai-chat との連携
ナレッジグラフを使用して、構造化された関係で LLM のコンテキストを充実させます。
auth-security(ReBAC)との連携
関係に基づくアクセス制御を実装します:「ユーザーXは関係Zを通じてリソースYにアクセスできますか?」
一般的なスキーマパターン
スタースキーマ(ハブとスポーク)
(:User)-[:PURCHASED]->(:Product)
(:User)-[:VIEWED]->(:Product)
(:User)-[:RATED]->(:Product)
階層スキーマ(ツリー)
(:CEO)-[:MANAGES]->(:VP)-[:MANAGES]->(:Director)
時系列スキーマ(イベントシーケンス)
(:Event {timestamp})-[:NEXT]->(:Event {timestamp})
はじめに
- データベースを選択する:上記の判断フレームワークを使用します
- スキーマを設計する:
references/graph-modeling.mdを参照します - クエリを実装する:
references/cypher-patterns.mdのパターンを使用します - 検証する:
scripts/validate_graph_schema.pyを実行します - 最適化する:インデックスを追加し、トラバーサルに上限を設定し、集計をキャッシュします
さらに読む
references/neo4j.md- Neo4j のセットアップ、ドライバー、GDS アルゴリズムreferences/arangodb.md- ArangoDB のマルチモデルパターンreferences/cypher-patterns.md- 包括的な Cypher クエリライブラリreferences/graph-modeling.md- データモデリングのベストプラクティスexamples/social-graph/- ソーシャルネットワークの完全な実装examples/knowledge-graph/- AI/RAG 向けのベクトル検索とグラフ検索のハイブリッド