AI

グラフDB比較:Neo4j vs ArangoDB vs Dgraph でグラフデータを管理する

オープンソースラボ編集部2026年6月14日

グラフDB比較:Neo4j vs ArangoDB vs Dgraph でグラフデータを管理する

SNSの「友人の友人」・レコメンデーション・知識グラフ・不正検知などエンティティ間のリレーションシップが複雑なデータを効率的に管理・クエリするのがグラフデータベースです。Neo4j(Cypher・最大シェア)・ArangoDB(マルチモデル・AQL)・Dgraph(GraphQL Native・分散)の3つが2026年のOSSグラフDBデファクトスタンダードです。

グラフデータベースを使う理由

  • 多段JOIN不要: RDBで「友人の友人の友人」を取得するには多重JOINが必要だがグラフDBは1クエリで取得可能
  • スキーマ柔軟: ノード(エンティティ)とエッジ(関係)を自由に追加してスキーマ変更コストを最小化
  • リレーション特化: フォロー関係・依存関係・知識グラフなど関係性の検索が高速
  • RAG知識グラフ: LLMのRAGシステムにグラフDBを組み合わせてGraphRAGを実現

主要データベースの概要

Neo4j

2007年公開、Java製のOSSです。GitHubスター13k+。世界最大シェアのグラフデータベースでCypher(グラフ特化クエリ言語)・APOC(300+のストアドプロシージャ)・Graph Data Science(GDS)ライブラリが充実しています。

# docker-compose.yml: Neo4j
version: "3.8"
services:
  neo4j:
    image: neo4j:5.25-community
    restart: unless-stopped
    ports:
      - "7474:7474"   # HTTP / Browser UI
      - "7687:7687"   # Bolt Protocol(クライアント接続)
    environment:
      NEO4J_AUTH: neo4j/${NEO4J_PASSWORD}
      NEO4J_PLUGINS: '["apoc", "graph-data-science"]'
      NEO4J_dbms_security_procedures_unrestricted: apoc.*,gds.*
      NEO4J_server_memory_heap_initial__size: 512m
      NEO4J_server_memory_heap_max__size: 2G
    volumes:
      - neo4j_data:/data
      - neo4j_logs:/logs
volumes:
  neo4j_data:
  neo4j_logs:
# Python: Neo4j でSNSグラフを構築して友人推薦を実装
from neo4j import GraphDatabase
from typing import Optional

driver = GraphDatabase.driver(
    'bolt://localhost:7687',
    auth=('neo4j', 'password'),
)

def create_user(tx, user_id: str, name: str, interests: list[str]):
    '''ユーザーノードを作成'''
    tx.run(
        'MERGE (u:User {id: $user_id}) '
        'SET u.name = $name, u.interests = $interests',
        user_id=user_id, name=name, interests=interests,
    )

def follow_user(tx, from_id: str, to_id: str):
    '''フォロー関係を作成'''
    tx.run(
        'MATCH (a:User {id: $from_id}), (b:User {id: $to_id}) '
        'MERGE (a)-[:FOLLOWS]->(b)',
        from_id=from_id, to_id=to_id,
    )

def get_friend_recommendations(tx, user_id: str, limit: int = 10) -> list[dict]:
    '''「友人の友人」でまだフォローしていないユーザーを推薦'''
    result = tx.run('''
        MATCH (me:User {id: $user_id})-[:FOLLOWS]->(friend)-[:FOLLOWS]->(recommended)
        WHERE NOT (me)-[:FOLLOWS]->(recommended)
          AND recommended.id <> $user_id
        WITH recommended, COUNT(DISTINCT friend) AS mutual_count
        ORDER BY mutual_count DESC
        LIMIT $limit
        RETURN recommended.id AS id,
               recommended.name AS name,
               mutual_count AS mutual_friends
    ''', user_id=user_id, limit=limit)
    return [dict(record) for record in result]

def find_shortest_path(tx, from_id: str, to_id: str) -> Optional[list]:
    '''2ユーザー間の最短パス(6次の隔たり)を探索'''
    result = tx.run('''
        MATCH path = shortestPath(
            (a:User {id: $from_id})-[:FOLLOWS*..6]->(b:User {id: $to_id})
        )
        RETURN [node IN nodes(path) | node.name] AS path_names,
               length(path) AS degree_of_separation
    ''', from_id=from_id, to_id=to_id)
    record = result.single()
    return record['path_names'] if record else None

# Graph Data Science: ページランクアルゴリズム(インフルエンサー検出)
def run_pagerank(session):
    # プロジェクショングラフを作成
    session.run('''
        CALL gds.graph.project(
            'social-graph',
            'User',
            'FOLLOWS'
        )
    ''')
    # PageRankを実行
    result = session.run('''
        CALL gds.pageRank.stream('social-graph')
        YIELD nodeId, score
        RETURN gds.util.asNode(nodeId).name AS name, score
        ORDER BY score DESC
        LIMIT 10
    ''')
    return [dict(r) for r in result]

# データ挿入
with driver.session() as session:
    session.execute_write(create_user, 'u1', '丸山侑太', ['AI', 'Python', 'Web'])
    session.execute_write(create_user, 'u2', '田中花子', ['AI', 'Design', 'React'])
    session.execute_write(create_user, 'u3', '佐藤太郎', ['Python', 'Data Science'])
    session.execute_write(follow_user, 'u1', 'u2')
    session.execute_write(follow_user, 'u2', 'u3')

    # 友人推薦
    recs = session.execute_read(get_friend_recommendations, 'u1')
    print('推薦:', recs)

    # 最短パス
    path = session.execute_read(find_shortest_path, 'u1', 'u3')
    print('パス:', path)

driver.close()

ArangoDB

2011年公開、C++製のOSSです。GitHubスター13k+。ドキュメント・グラフ・キーバリューを1つのデータベースで管理できるマルチモデルDBです。AQL(ArangoDB Query Language)でJSONドキュメントとグラフを横断したクエリが可能です。

// ArangoDB: JavaScriptドライバーでのグラフ操作
const { Database } = require('arangojs')

const db = new Database({ url: 'http://localhost:8529', auth: { username: 'root', password: 'password' } })

// グラフ定義(エッジコレクション + ノードコレクション)
await db.createGraph('social', {
  edgeDefinitions: [{
    collection: 'follows',
    from: ['users'],
    to: ['users'],
  }],
})

// ノード(ユーザー)を追加
const users = db.collection('users')
const u1 = await users.save({ _key: 'user1', name: '丸山侑太', age: 30 })
const u2 = await users.save({ _key: 'user2', name: '田中花子', age: 25 })

// エッジ(フォロー関係)を追加
const follows = db.collection('follows')
await follows.save({ _from: 'users/user1', _to: 'users/user2', since: '2026-01-01' })

// AQL: グラフトラバーサル(2段階先まで)
const cursor = await db.query(`
    FOR user IN 1..2 OUTBOUND 'users/user1' GRAPH 'social'
    RETURN DISTINCT { name: user.name, depth: LENGTH(user._id) }
`)
const result = await cursor.all()

Dgraph

2016年公開、Go製のOSSです。GitHubスター20k+。GraphQL Nativeな分散グラフデータベースで、GraphQLスキーマを定義するだけでCRUD APIが自動生成されます。分散クラスター構成・水平スケーリングに強みがあります。

機能比較表

比較項目Neo4jArangoDBDgraph
クエリ言語CypherAQLGraphQL
マルチモデル
GDSアルゴリズム✅ 最充実
分散スケール
セットアップ✅ 容易✅ 容易
GitHub Stars13k+13k+20k+

グラフDBはLLM Toolsカテゴリ/categories/llm-toolsのRAGシステムと組み合わせてGraphRAG(グラフ拡張RAG)を構築します。エンティティ間の関係をグラフDBに格納してLLMの回答生成時にグラフトラバーサルで関連コンテキストを取得する手法がMicrosoftのGraphRAG研究で注目されています。DevOpsカテゴリ/categories/devopsのApache Kafkaとイベントストリームでグラフ更新をリアルタイム反映する不正検知システムにも活用されます。

FAQ

Q. Neo4jのCypherの基本構文を教えてください。

A. MATCH(データ取得)・CREATE(作成)・MERGE(存在確認後作成)・WHERE(フィルター)・RETURN(返却)がコアキーワードです。ノード作成: CREATE (n:User {name: '丸山', age: 30})。ノード検索: MATCH (n:User) WHERE n.age > 25 RETURN n.name, n.age。関係作成: MATCH (a:User {name: '丸山'}), (b:User {name: '田中'}) CREATE (a)-[:FOLLOWS {since: date()}]->(b)。パターンマッチ(多段関係): MATCH (a)-[:FOLLOWS*1..3]->(b) WHERE a.name = '丸山' RETURN DISTINCT b.name。集計: MATCH (u:User)-[:FOLLOWS]->(f) RETURN u.name, COUNT(f) AS following_count ORDER BY following_count DESC LIMIT 10

Q. Neo4jとRelational DB(PostgreSQL)の使い分けは?

A. 関係が複雑・多対多・多段トラバーサルが頻繁ならNeo4jシンプルなCRUD・集計・レポーティング中心ならPostgreSQLが向いています。Neo4j優位ケース: ①SNS(友人の友人)②レコメンデーション(「この商品を買った人はこんな商品も買っています」)③不正検知(異常な取引ネットワーク)④知識グラフ(GraphRAG)⑤サプライチェーン・依存関係分析。PostgreSQLで十分なケース: ①ユーザー・注文・商品のCRUD②集計・レポート(GROUP BY・SUM)③シンプルな外部キー参照(ユーザー→注文)。両方使う構成: PostgreSQLをメインDB・Neo4jをグラフ特化クエリ用のサブDBとして使い分けるハイブリッド構成も実績があります。

Q. GraphRAG(グラフ拡張RAG)をNeo4jで実装するには?

A. ドキュメントからエンティティを抽出してNeo4jに格納し、クエリ時にグラフトラバーサルでコンテキストを拡張します。実装ステップ: ①LLM(Claude API)でドキュメントから「エンティティ(人名・組織・概念)」と「関係(AはBを所有する・CはDと協業)」を抽出②抽出したエンティティをNeo4jのNodeとして追加③関係をEdgeとして追加④クエリ時: まずベクター検索でシード文書を取得→Neo4jで関連エンティティを2〜3段階トラバーサルして追加コンテキストを取得→拡張コンテキストをLLMに渡して回答生成。LangChain Neo4j統合: from langchain_community.graphs import Neo4jGraphでLangChainから直接Neo4jに接続できます。

Q. ArangoDBのマルチモデル機能をどんな場面で使いますか?

A. 1つのデータが「ドキュメント」と「グラフノード」の両方として機能する場面で有効です。実例: Eコマース: ①ユーザー・商品・注文をJSONドキュメントとして管理(NoSQL的な柔軟な属性)②同時に「ユーザー→購入→商品」「商品→カテゴリ」をグラフエッジとして管理③AQLで「ユーザーが購入した商品を3段階先まで辿って同じ商品を買ったユーザーが購入した他商品」をJOINなしで取得。利点: PostgreSQL(リレーション)+ Redis(セッション)+ Neo4j(グラフ)の3DBが1つのArangoDBに統合できてインフラが簡素化されます。

まとめ

ユースケース推奨ツール
SNS・GraphRAG・Cypher・GDSアルゴリズムNeo4j
マルチモデル・AQL・ドキュメント+グラフ統合ArangoDB
GraphQL Native・分散・水平スケールDgraph

関連外部リソース

他の記事も読む

Let's Build Together

OSS導入、自社だけで悩まない。

ツール選定から構築・運用・AI活用まで、オープンソースラボ運営元のClasslessが伴走します。初回のご相談は無料です。