🤖

Neo4jとPythonで始めるグラフデータベース入門

2025/02/07に公開

Neo4jとPythonで始めるグラフデータベース入門

今回は、Neo4jグラフデータベースをPythonから操作する方法について、実践的なチュートリアルを通じて解説していきます。

はじめに

グラフデータベースって何?

従来のリレーショナルデータベース(RDB)では、データを表(テーブル)で管理していましたが、グラフデータベースでは、データを「ノード」と「関係」として管理します。これにより、複雑な関係性を持つデータを直感的に表現できます。

Neo4jの特徴

Neo4jは人気のあるグラフデータベースの1つで、以下のような特徴があります:

  • 直感的なクエリ言語(Cypher)
  • 高いパフォーマンス
  • 豊富な視覚化ツール
  • 様々な言語のドライバーサポート

環境構築

今回は、Dockerを使用して簡単に環境を構築します。

必要なファイル

  1. docker-compose.yml:
services:
  neo4j:
    image: neo4j:4.2.5
    platform: linux/amd64
    container_name: my_neo4j
    ports:
      - 7474:7474
      - 7687:7687
    environment:
      - NEO4J_AUTH=neo4j/docker

  python:
    build: ./python_docker
    volumes:
      - ./src:/app/src
    tty: true
  1. requirements.txt:
neo4j-driver==4.4.4

セットアップ手順

  1. プロジェクトディレクトリを作成
  2. 必要なファイルを配置
  3. docker-compose up -d で環境を起動

基本的なCRUD操作の実装

1. データベース接続

from neo4j import GraphDatabase

class Neo4jCRUD:
    def __init__(self, uri, user, password):
        self.driver = GraphDatabase.driver(uri, auth=(user, password))

2. Create操作(データの作成)

def create_user(self, name, age):
    with self.driver.session() as session:
        result = session.write_transaction(
            self._create_user, name, age
        )
        return result

@staticmethod
def _create_user(tx, name, age):
    query = (
        "CREATE (u:User {name: $name, age: $age}) "
        "RETURN u.name, u.age"
    )
    result = tx.run(query, name=name, age=age)
    return result.single()

このコードでは、Userノードを作成し、名前と年齢を属性として設定しています。

3. Read操作(データの読み取り)

def get_all_users(self):
    with self.driver.session() as session:
        return session.read_transaction(self._get_all_users)

@staticmethod
def _get_all_users(tx):
    query = "MATCH (u:User) RETURN u.name, u.age"
    result = tx.run(query)
    return [{"name": record["u.name"], "age": record["u.age"]} 
            for record in result]

MATCH句を使用して、すべてのUserノードを検索します。

4. Update操作(データの更新)

def update_user_age(self, name, new_age):
    with self.driver.session() as session:
        return session.write_transaction(
            self._update_user_age, name, new_age
        )

5. Delete操作(データの削除)

def delete_user(self, name):
    with self.driver.session() as session:
        return session.write_transaction(self._delete_user, name)

実践的なユースケース

ユーザー管理システムの実装

crud = Neo4jCRUD("bolt://neo4j:7687", "neo4j", "docker")

# ユーザーの作成
crud.create_user("田中", 25)
crud.create_user("鈴木", 30)

# ユーザー情報の取得
users = crud.get_all_users()
for user in users:
    print(f"名前: {user['name']}, 年齢: {user['age']}")

# ユーザー情報の更新
crud.update_user_age("田中", 26)

# ユーザーの削除
crud.delete_user("鈴木")

エラーハンドリングのベストプラクティス

  1. 接続エラーの処理
def __init__(self, uri, user, password):
    try:
        self.driver = GraphDatabase.driver(uri, auth=(user, password))
        self.driver.verify_connectivity()
    except Exception as e:
        print(f"接続エラー: {e}")
        raise
  1. トランザクションの適切な管理
with self.driver.session() as session:
    try:
        result = session.write_transaction(self._create_user, name, age)
        return result
    except Exception as e:
        print(f"トランザクションエラー: {e}")
        raise

発展的な使い方

1. リレーションシップの作成

def create_friendship(self, user1_name, user2_name):
    query = """
    MATCH (u1:User {name: $user1_name})
    MATCH (u2:User {name: $user2_name})
    CREATE (u1)-[:FRIEND]->(u2)
    RETURN u1.name, u2.name
    """

2. 複雑なクエリの例

def find_friends_of_friends(self, user_name):
    query = """
    MATCH (u:User {name: $user_name})-[:FRIEND]->(f:User)-[:FRIEND]->(fof:User)
    WHERE u <> fof
    RETURN DISTINCT fof.name
    """

まとめ

Neo4jとPythonを組み合わせることで、複雑な関係性を持つデータを効率的に管理できます。

Discussion