导航菜单

  • 1.langchain.intro
  • 2.langchain.chat_models
  • 3.langchain.prompts
  • 4.langchain.example_selectors
  • 5.output_parsers
  • 6.Runnable
  • 7.memory
  • 8.document_loaders
  • 9.text_splitters
  • 10.embeddings
  • 11.tool
  • 12.retrievers
  • 13.optimize
  • 14.项目介绍
  • 15.启动HTTP
  • 16.数据与模型
  • 17.权限管理
  • 18.知识库管理
  • 19.设置
  • 20.文档管理
  • 21.聊天
  • 22.API文档
  • 23.RAG优化
  • 24.索引时优化
  • 25.检索前优化
  • 26.检索后优化
  • 27.系统优化
  • 28.GraphRAG
  • 29.图
  • 30.为什么选择图数据库
  • 31.什么是 Neo4j
  • 32.安装和连接 Neo4j
  • 33.Neo4j核心概念
  • 34.Cypher基础
  • 35.模式匹配
  • 36.数据CRUD操作
  • 37.GraphRAG
  • 38.查询和过滤
  • 39.结果处理和聚合
  • 40.语句组合
  • 41.子查询
  • 42.模式和约束
  • 43.日期时间处理
  • 44.Cypher内置函数
  • 45.Python操作Neo4j
  • 46.neo4j
  • 47.py2neo
  • 48.Streamlit
  • 49.Pandas
  • 50.graphRAG
  • 51.deepdoc
  • 52.deepdoc
  • 53.deepdoc
  • 55.deepdoc
  • 54.deepdoc
  • Pillow
  • 1. 什么是 Py2neo?
    • 1.1 Py2neo 简介
    • 1.2 前置知识
    • 1.3 Py2neo vs 官方驱动
  • 2. 安装和连接
    • 2.1 安装 Py2neo
    • 2.2 连接数据库
  • 3. 核心数据模型
    • 3.1 节点 (Node)
    • 3.2 关系 (Relationship)
    • 3.3 将节点和关系保存到数据库
  • 4. 数据操作
    • 4.1 创建数据
    • 4.2 查询数据
    • 4.3 更新数据
    • 4.4 删除数据
  • 5. 路径查询
    • 5.1 什么是路径查询?
    • 5.2 路径查询示例
  • 6. 实际应用示例
    • 6.1 社交网络应用
    • 6.2 推荐系统应用
  • 7. 最佳实践
    • 7.1 使用事务批量操作
    • 7.2 使用 UNWIND 优化批量操作
  • 8. 小结
    • 8.1 核心概念回顾
    • 8.2 关键要点
    • 8.3 下一步学习

1. 什么是 Py2neo? #

1.1 Py2neo 简介 #

Py2neo 是一个高级、Pythonic 的客户端库,用于连接和操作 Neo4j 图数据库。

为什么选择 Py2neo?

想象一下,你要操作 Neo4j 图数据库,有两种方式:

  • 官方 neo4j 驱动:需要写 Cypher 查询语句,类似 SQL
  • Py2neo:用 Python 对象的方式操作,更符合 Python 开发者的习惯

Py2neo 就像是一个"翻译官",把 Python 代码翻译成 Cypher 查询,让你用 Python 的方式操作图数据库。

Py2neo 的特点:

  • Pythonic API:符合 Python 开发者习惯,代码更简洁
  • 对象导向:节点、关系都是 Python 对象,操作更直观
  • 快速开发:减少了学习 Cypher 的成本
  • 良好抽象:对图数据库操作进行了高度封装

1.2 前置知识 #

在学习本教程之前,你需要掌握:

  • Python 基础:变量、函数、类、异常处理
  • Neo4j 基础:了解什么是节点、关系、属性(如果不熟悉,建议先学习 Neo4j 基础)
  • 基本概念:图数据库的基本概念

如果你还不熟悉这些,建议先学习 Python 和 Neo4j 的基础知识。

1.3 Py2neo vs 官方驱动 #

特性 官方 neo4j 驱动 Py2neo
API 风格 原生、底层、基于查询语句 高级、Pythonic、对象导向
学习曲线 较陡峭,需熟悉 Cypher 平缓,Python 开发者友好
主要用途 高性能、精细化控制 快速开发、数据建模
代码示例 driver.execute_query("MATCH...") graph.create(node)

选择建议:

  • 如果你是 Python 开发者,想快速上手,选择 Py2neo
  • 如果你需要高性能和精细控制,选择 官方驱动

2. 安装和连接 #

2.1 安装 Py2neo #

在开始之前,我们需要先安装 Py2neo。

安装步骤:

# 使用 pip 安装 Py2neo
# pip 是 Python 的包管理工具
pip install py2neo

验证安装:

# 导入 py2neo 库,如果没有错误说明安装成功
import py2neo
print(f"Py2neo 版本:{py2neo.__version__}")

2.2 连接数据库 #

连接 Neo4j 数据库是使用 Py2neo 的第一步。

前置知识:Neo4j 连接信息

在连接之前,你需要知道:

  • URI:数据库地址,格式为 bolt://主机:端口
  • 认证信息:用户名和密码
  • 默认端口:Neo4j 的 Bolt 协议默认端口是 7687

完整示例:

# 导入 Py2neo 的核心类
# Graph 用于连接数据库
# Node 用于创建节点
# Relationship 用于创建关系
from py2neo import Graph, Node, Relationship

# 创建数据库连接
# Graph() 创建并返回一个图对象
# 第一个参数是数据库 URI(地址和端口)
# auth 参数是认证信息,格式为 (用户名, 密码)
# name 参数指定数据库名称(Neo4j 4.0+ 支持多数据库)
graph = Graph(
    "bolt://localhost:7687",  # 本地数据库地址
    auth=("neo4j", "password"),  # 用户名和密码
    name="neo4j"  # 数据库名称
)

# 验证连接
# run() 方法执行 Cypher 查询
# "RETURN 1" 是一个简单的测试查询
# data() 方法获取查询结果
try:
    result = graph.run("RETURN 1").data()
    print("✅ 连接成功!")
except Exception as e:
    print(f"❌ 连接失败:{e}")

常见问题:

  • 如果提示连接失败,请检查 Neo4j 是否已启动
  • 如果提示认证失败,请检查用户名和密码是否正确
  • 如果使用远程数据库,请将 localhost 替换为实际的 IP 地址

3. 核心数据模型 #

3.1 节点 (Node) #

节点是图数据库中的基本元素,用来表示实体,如人、商品、地点等。

节点的组成:

  • 标签(Label):节点的类型,如 "Person"、"Product"
  • 属性(Properties):节点的数据,如姓名、年龄等

创建节点示例:

# 导入 Node 类
from py2neo import Node

# 创建简单节点
# Node() 创建节点对象
# 第一个参数是标签(节点类型)
# 后面的参数是节点的属性(键值对)
person = Node(
    "Person",  # 标签:节点类型
    name="Alice",  # 属性:姓名
    age=30,  # 属性:年龄
    city="北京"  # 属性:城市
)

# 打印节点信息
# 节点对象可以直接打印,显示标签和属性
print(person)
# 输出:(:Person {age: 30, city: '北京', name: 'Alice'})

# 访问节点属性
# 节点对象可以像字典一样访问属性
print(f"姓名:{person['name']}")
print(f"年龄:{person['age']}")

# 修改节点属性
# 可以直接修改属性值
person['age'] = 31
print(f"更新后的年龄:{person['age']}")

批量创建节点示例:

# 导入 Node 类
from py2neo import Node

# 准备数据
# 使用列表存储多个人的信息
people_data = [
    {"name": "张三", "age": 25, "job": "工程师"},
    {"name": "李四", "age": 28, "job": "设计师"},
    {"name": "王五", "age": 35, "job": "经理"}
]

# 批量创建节点
# 使用列表推导式创建多个节点
# **data 表示将字典展开为关键字参数
people_nodes = [Node("Person", **data) for data in people_data]

# 打印所有节点
for node in people_nodes:
    print(node)

3.2 关系 (Relationship) #

关系用来连接两个节点,表示它们之间的关联,如"朋友"、"购买"等。

关系的组成:

  • 起始节点:关系的起点
  • 关系类型:关系的名称,如 "KNOWS"、"BOUGHT"
  • 结束节点:关系的终点
  • 属性:关系的附加信息,如时间、强度等

创建关系示例:

# 导入必要的类
from py2neo import Node, Relationship

# 创建两个节点
# 创建 Alice 节点
alice = Node("Person", name="Alice", age=30)

# 创建 Bob 节点
bob = Node("Person", name="Bob", age=25)

# 创建基础关系
# Relationship() 创建关系对象
# 第一个参数是起始节点
# 第二个参数是关系类型(字符串)
# 第三个参数是结束节点
# 后面的参数是关系的属性(可选)
knows = Relationship(alice, "KNOWS", bob, since=2020)

# 打印关系信息
print(knows)
# 输出:(Alice)-[:KNOWS {since: 2020}]->(Bob)

# 访问关系属性
# 关系对象可以像字典一样访问属性
print(f"认识时间:{knows['since']}")

# 创建带多个属性的关系
# 关系可以有多个属性
works_with = Relationship(
    alice,  # 起始节点
    "WORKS_WITH",  # 关系类型
    bob,  # 结束节点
    department="工程部",  # 关系属性:部门
    projects=["项目A", "项目B"]  # 关系属性:项目列表
)

# 打印关系信息
print(works_with)

3.3 将节点和关系保存到数据库 #

创建节点和关系后,需要将它们保存到数据库中。

完整示例:

# 导入必要的类
from py2neo import Graph, Node, Relationship

# 创建数据库连接
graph = Graph("bolt://localhost:7687", auth=("neo4j", "password"))

# 创建节点
alice = Node("Person", name="Alice", age=30)
bob = Node("Person", name="Bob", age=25)

# 创建关系
knows = Relationship(alice, "KNOWS", bob, since=2020)

# 方法1:分别保存节点和关系
# create() 方法将节点或关系保存到数据库
graph.create(alice)  # 保存 Alice 节点
graph.create(bob)  # 保存 Bob 节点
graph.create(knows)  # 保存关系

# 方法2:使用子图一次性保存
# 使用 | 运算符组合节点和关系创建子图
# 子图是节点和关系的集合
subgraph = alice | knows | bob

# 一次性保存整个子图
# 这样更高效,因为只需要一次数据库操作
graph.create(subgraph)

print("✅ 数据保存成功!")

4. 数据操作 #

4.1 创建数据 #

在实际应用中,我们需要创建节点和关系。

前置知识:MERGE vs CREATE

  • CREATE:总是创建新节点,如果已存在会创建重复节点
  • MERGE:如果节点不存在则创建,如果已存在则不创建(避免重复)

创建节点示例:

# 导入必要的类
from py2neo import Graph, Node

# 创建数据库连接
graph = Graph("bolt://localhost:7687", auth=("neo4j", "password"))

# 方法1:直接创建
# 创建节点对象
person = Node("Person", name="Alice", age=30)

# 保存到数据库
# create() 方法将节点保存到数据库
graph.create(person)

print("✅ 节点创建成功!")

# 方法2:使用 MERGE(推荐)
# 如果节点已存在,则不创建;如果不存在,则创建
# 这样可以避免重复创建
query = """
MERGE (p:Person {name: $name})
SET p.age = $age
RETURN p
"""

# 执行查询
# run() 方法执行 Cypher 查询
# 第一个参数是查询语句
# 后面的参数是查询参数
result = graph.run(query, name="Alice", age=30)

# 获取结果
# data() 方法获取查询结果(列表)
data = result.data()
print(f"创建/更新了节点:{data}")

创建关系示例:

# 导入必要的类
from py2neo import Graph, Node, Relationship

# 创建数据库连接
graph = Graph("bolt://localhost:7687", auth=("neo4j", "password"))

# 首先确保节点存在
# 使用 MERGE 确保节点存在
graph.run("""
MERGE (a:Person {name: $name1})
MERGE (b:Person {name: $name2})
""", name1="Alice", name2="Bob")

# 方法1:使用 Relationship 对象
# 先查找节点(后面会介绍如何查找)
# 这里假设节点已存在
alice = Node("Person", name="Alice")
bob = Node("Person", name="Bob")

# 创建关系对象
knows = Relationship(alice, "KNOWS", bob, since=2020)

# 保存关系
# 注意:如果节点不存在,需要先创建节点
graph.create(knows)

# 方法2:使用 Cypher 查询(推荐)
# 使用 MERGE 创建关系,如果已存在则不创建
query = """
MATCH (a:Person {name: $name1})
MATCH (b:Person {name: $name2})
MERGE (a)-[r:KNOWS {since: $since}]->(b)
RETURN r
"""

# 执行查询
result = graph.run(query, name1="Alice", name2="Bob", since=2020)
print("✅ 关系创建成功!")

4.2 查询数据 #

查询是图数据库最常用的操作。Py2neo 提供了多种查询方式。

前置知识:NodeMatcher

NodeMatcher 是 Py2neo 提供的节点匹配器,用于查找节点,类似于 ORM 的查询接口。

使用 NodeMatcher 查询示例:

# 导入必要的类
from py2neo import Graph, NodeMatcher

# 创建数据库连接
graph = Graph("bolt://localhost:7687", auth=("neo4j", "password"))

# 创建节点匹配器
# NodeMatcher() 创建匹配器对象
# 参数是图对象
matcher = NodeMatcher(graph)

# 简单查询:查找所有 Person 节点
# match() 方法匹配节点
# 第一个参数是标签(节点类型)
# 返回所有匹配的节点
all_people = matcher.match("Person").all()

# 打印所有节点
for person in all_people:
    print(f"姓名:{person['name']}, 年龄:{person['age']}")

# 条件查询:查找特定年龄的人
# where() 方法添加条件
# _ 表示当前节点
young_people = matcher.match("Person").where("_.age = 30").all()

# 打印结果
for person in young_people:
    print(f"姓名:{person['name']}")

# 查找单个节点
# first() 方法返回第一个匹配的节点,如果没有则返回 None
alice = matcher.match("Person", name="Alice").first()

# 检查是否找到
if alice:
    print(f"找到:{alice['name']}")
else:
    print("未找到")

使用 Cypher 查询示例:

# 导入必要的类
from py2neo import Graph

# 创建数据库连接
graph = Graph("bolt://localhost:7687", auth=("neo4j", "password"))

# 执行 Cypher 查询
# run() 方法执行查询
# 第一个参数是 Cypher 查询语句
# 后面的参数是查询参数
result = graph.run("""
MATCH (p:Person)-[r:KNOWS]->(friend:Person)
WHERE p.age > $min_age
RETURN p.name, friend.name, r.since
ORDER BY p.name
""", min_age=25)

# 处理查询结果
# result 是一个游标对象,可以遍历
for record in result:
    # record 是一个字典,包含查询返回的字段
    person_name = record['p.name']
    friend_name = record['friend.name']
    since = record['r.since']
    print(f"{person_name} 认识 {friend_name} 从 {since} 年")

# 获取所有结果
# data() 方法返回所有结果的列表
all_data = result.data()
print(f"共找到 {len(all_data)} 条记录")

4.3 更新数据 #

更新节点属性是常见的操作。

更新节点示例:

# 导入必要的类
from py2neo import Graph, NodeMatcher
from datetime import datetime

# 创建数据库连接
graph = Graph("bolt://localhost:7687", auth=("neo4j", "password"))

# 创建节点匹配器
matcher = NodeMatcher(graph)

# 查找要更新的节点
# 使用匹配器查找节点
alice = matcher.match("Person", name="Alice").first()

# 检查节点是否存在
if alice:
    # 修改节点属性
    # 节点对象可以像字典一样修改属性
    alice["age"] = 31  # 更新年龄
    alice["last_updated"] = datetime.now()  # 添加更新时间

    # 保存更改
    # push() 方法将节点的更改推送到数据库
    graph.push(alice)

    print("✅ 节点更新成功!")
else:
    print("❌ 节点不存在")

# 批量更新
# 使用 Cypher 查询批量更新
query = """
MATCH (p:Person)
WHERE p.age < 30
SET p.status = 'young',
    p.updated = timestamp()
RETURN count(p) as updated_count
"""

# 执行更新查询
result = graph.run(query)

# 获取更新数量
# data() 方法返回结果列表
# [0] 获取第一条记录
updated_count = result.data()[0]['updated_count']
print(f"更新了 {updated_count} 个节点")

4.4 删除数据 #

删除节点和关系也是常见的操作。

删除节点示例:

# 导入必要的类
from py2neo import Graph

# 创建数据库连接
graph = Graph("bolt://localhost:7687", auth=("neo4j", "password"))

# 方法1:使用 Cypher 删除节点
# DETACH DELETE 会删除节点及其所有关系
query = """
MATCH (p:Person {name: $name})
DETACH DELETE p
RETURN count(p) as deleted_count
"""

# 执行删除查询
result = graph.run(query, name="Alice")

# 获取删除数量
deleted_count = result.data()[0]['deleted_count']
print(f"删除了 {deleted_count} 个节点")

# 方法2:条件删除
# 删除满足条件的多个节点
graph.run("""
MATCH (p:Person)
WHERE p.age < 18
DETACH DELETE p
""")

print("✅ 删除完成!")

5. 路径查询 #

5.1 什么是路径查询? #

路径查询是图数据库的特色功能,用于查找两个节点之间的路径,如"朋友的朋友"、"推荐路径"等。

路径查询的应用场景:

  • 社交网络:查找朋友的朋友
  • 推荐系统:查找相似产品
  • 知识图谱:查找概念之间的关联

5.2 路径查询示例 #

查找朋友的朋友示例:

# 导入必要的类
from py2neo import Graph

# 创建数据库连接
graph = Graph("bolt://localhost:7687", auth=("neo4j", "password"))

# 查找朋友的朋友
# [*1..2] 表示路径长度为 1 到 2(1度或2度关系)
# length(r) 计算路径长度
query = """
MATCH (me:Person {name: $name})-[r:KNOWS*1..2]-(friend:Person)
WHERE me <> friend
RETURN friend.name AS name, length(r) AS distance
ORDER BY distance
"""

# 执行查询
result = graph.run(query, name="Alice")

# 处理结果
print("朋友的朋友:")
for record in result:
    name = record['name']
    distance = record['distance']
    print(f"  {name} (距离:{distance})")

查找最短路径示例:

# 导入必要的类
from py2neo import Graph

# 创建数据库连接
graph = Graph("bolt://localhost:7687", auth=("neo4j", "password"))

# 查找两个节点之间的最短路径
# shortestPath() 函数查找最短路径
# [*] 表示任意长度的路径
query = """
MATCH path = shortestPath(
    (a:Person {name: $name1})-[*]-(b:Person {name: $name2})
)
RETURN [node IN nodes(path) | node.name] AS path,
       length(path) AS depth
"""

# 执行查询
result = graph.run(query, name1="Alice", name2="Bob")

# 处理结果
for record in result:
    path = record['path']
    depth = record['depth']
    print(f"路径:{' -> '.join(path)}")
    print(f"深度:{depth}")

6. 实际应用示例 #

6.1 社交网络应用 #

让我们创建一个完整的社交网络应用示例。

完整示例:

# 导入必要的类
from py2neo import Graph, Node, Relationship, NodeMatcher
from datetime import datetime

# 创建数据库连接
graph = Graph("bolt://localhost:7687", auth=("neo4j", "password"))

# 创建节点匹配器
matcher = NodeMatcher(graph)

class SocialNetwork:
    """社交网络应用类"""

    def __init__(self, graph):
        """
        初始化社交网络应用

        参数:
        - graph: 图数据库连接对象
        """
        # 保存图对象
        self.graph = graph

        # 创建节点匹配器
        self.matcher = NodeMatcher(graph)

    def add_user(self, name, age, city):
        """
        添加用户

        参数:
        - name: 姓名
        - age: 年龄
        - city: 城市

        返回:
        - 创建的节点
        """
        # 使用 MERGE 确保用户不存在时才创建
        query = """
        MERGE (u:User {name: $name})
        SET u.age = $age, u.city = $city
        RETURN u
        """

        # 执行查询
        result = self.graph.run(query, name=name, age=age, city=city)

        # 返回创建的节点
        return result.data()[0]['u']

    def add_friendship(self, name1, name2):
        """
        添加朋友关系

        参数:
        - name1: 第一个人的姓名
        - name2: 第二个人的姓名

        返回:
        - 创建的关系
        """
        # 使用 MERGE 创建朋友关系
        query = """
        MATCH (u1:User {name: $name1})
        MATCH (u2:User {name: $name2})
        MERGE (u1)-[r:FRIEND {since: $since}]->(u2)
        RETURN r
        """

        # 执行查询
        # since 属性记录成为朋友的时间
        result = self.graph.run(
            query,
            name1=name1,
            name2=name2,
            since=datetime.now().year
        )

        # 返回创建的关系
        return result.data()[0]['r']

    def get_friends(self, name):
        """
        获取某个人的所有朋友

        参数:
        - name: 姓名

        返回:
        - 朋友列表
        """
        # 查找所有朋友
        query = """
        MATCH (user:User {name: $name})-[:FRIEND]-(friend:User)
        RETURN friend.name AS name, friend.age AS age
        """

        # 执行查询
        result = self.graph.run(query, name=name)

        # 转换为列表
        friends = []
        for record in result:
            friends.append({
                "name": record['name'],
                "age": record['age']
            })

        return friends

    def recommend_friends(self, name, limit=5):
        """
        推荐朋友(朋友的朋友)

        参数:
        - name: 姓名
        - limit: 推荐数量

        返回:
        - 推荐的朋友列表
        """
        # 查找朋友的朋友(2度关系)
        # 排除已经是朋友的人
        query = """
        MATCH (user:User {name: $name})-[:FRIEND]-(friend)-[:FRIEND]-(potential:User)
        WHERE user <> potential
        AND NOT (user)-[:FRIEND]-(potential)
        WITH potential, COUNT(DISTINCT friend) AS common_friends
        RETURN potential.name AS name, common_friends
        ORDER BY common_friends DESC
        LIMIT $limit
        """

        # 执行查询
        result = self.graph.run(query, name=name, limit=limit)

        # 转换为列表
        recommendations = []
        for record in result:
            recommendations.append({
                "name": record['name'],
                "common_friends": record['common_friends']
            })

        return recommendations


# 使用示例
if __name__ == "__main__":
    # 创建社交网络应用
    social = SocialNetwork(graph)

    # 添加用户
    social.add_user("张三", 25, "北京")
    social.add_user("李四", 30, "上海")
    social.add_user("王五", 28, "广州")
    social.add_user("赵六", 32, "深圳")

    # 添加朋友关系
    social.add_friendship("张三", "李四")
    social.add_friendship("张三", "王五")
    social.add_friendship("李四", "赵六")
    social.add_friendship("王五", "赵六")

    # 获取朋友列表
    print("张三的朋友:")
    friends = social.get_friends("张三")
    for friend in friends:
        print(f"  {friend['name']} ({friend['age']} 岁)")

    # 推荐朋友
    print("\n为张三推荐朋友:")
    recommendations = social.recommend_friends("张三", limit=5)
    for rec in recommendations:
        print(f"  {rec['name']} (共同朋友数:{rec['common_friends']})")

6.2 推荐系统应用 #

让我们创建一个简单的产品推荐系统。

完整示例:

# 导入必要的类
from py2neo import Graph

# 创建数据库连接
graph = Graph("bolt://localhost:7687", auth=("neo4j", "password"))

class RecommendationSystem:
    """产品推荐系统"""

    def __init__(self, graph):
        """
        初始化推荐系统

        参数:
        - graph: 图数据库连接对象
        """
        # 保存图对象
        self.graph = graph

    def add_user(self, user_id, name):
        """
        添加用户

        参数:
        - user_id: 用户ID
        - name: 姓名
        """
        # 使用 MERGE 创建用户节点
        query = """
        MERGE (u:User {id: $user_id})
        SET u.name = $name
        RETURN u
        """

        # 执行查询
        self.graph.run(query, user_id=user_id, name=name)

    def add_product(self, product_id, name, category):
        """
        添加产品

        参数:
        - product_id: 产品ID
        - name: 产品名称
        - category: 产品类别
        """
        # 使用 MERGE 创建产品节点
        query = """
        MERGE (p:Product {id: $product_id})
        SET p.name = $name, p.category = $category
        RETURN p
        """

        # 执行查询
        self.graph.run(query, product_id=product_id, name=name, category=category)

    def add_purchase(self, user_id, product_id):
        """
        添加购买关系

        参数:
        - user_id: 用户ID
        - product_id: 产品ID
        """
        # 使用 MERGE 创建购买关系
        query = """
        MATCH (u:User {id: $user_id})
        MATCH (p:Product {id: $product_id})
        MERGE (u)-[r:BOUGHT]->(p)
        RETURN r
        """

        # 执行查询
        self.graph.run(query, user_id=user_id, product_id=product_id)

    def add_similarity(self, product_id1, product_id2):
        """
        添加产品相似关系

        参数:
        - product_id1: 第一个产品ID
        - product_id2: 第二个产品ID
        """
        # 使用 MERGE 创建相似关系
        query = """
        MATCH (p1:Product {id: $product_id1})
        MATCH (p2:Product {id: $product_id2})
        MERGE (p1)-[r:SIMILAR_TO]->(p2)
        RETURN r
        """

        # 执行查询
        self.graph.run(query, product_id1=product_id1, product_id2=product_id2)

    def recommend_products(self, user_id, limit=10):
        """
        推荐产品

        参数:
        - user_id: 用户ID
        - limit: 推荐数量

        返回:
        - 推荐产品列表
        """
        # 查找推荐产品
        # 逻辑:找到用户购买过的产品,然后找到与这些产品相似的产品
        # 排除用户已经购买过的产品
        query = """
        MATCH (u:User {id: $user_id})-[:BOUGHT]->(p:Product)
        MATCH (p)-[:SIMILAR_TO]->(recommendation:Product)
        WHERE NOT EXISTS((u)-[:BOUGHT]->(recommendation))
        WITH recommendation, COUNT(p) AS similarity_score
        RETURN recommendation.name AS name, similarity_score
        ORDER BY similarity_score DESC
        LIMIT $limit
        """

        # 执行查询
        result = self.graph.run(query, user_id=user_id, limit=limit)

        # 转换为列表
        recommendations = []
        for record in result:
            recommendations.append({
                "name": record['name'],
                "score": record['similarity_score']
            })

        return recommendations


# 使用示例
if __name__ == "__main__":
    # 创建推荐系统
    recommender = RecommendationSystem(graph)

    # 添加用户
    recommender.add_user("u1", "张三")
    recommender.add_user("u2", "李四")

    # 添加产品
    recommender.add_product("p1", "笔记本电脑", "电子产品")
    recommender.add_product("p2", "鼠标", "电子产品")
    recommender.add_product("p3", "键盘", "电子产品")

    # 添加购买关系
    recommender.add_purchase("u1", "p1")
    recommender.add_purchase("u1", "p2")

    # 添加产品相似关系
    recommender.add_similarity("p1", "p2")
    recommender.add_similarity("p1", "p3")
    recommender.add_similarity("p2", "p3")

    # 推荐产品
    print("为张三推荐产品:")
    recommendations = recommender.recommend_products("u1", limit=5)
    for rec in recommendations:
        print(f"  {rec['name']} (相似度分数:{rec['score']})")

7. 最佳实践 #

7.1 使用事务批量操作 #

当需要创建大量数据时,使用事务可以提高性能。

完整示例:

# 导入必要的类
from py2neo import Graph, Node, Transaction

# 创建数据库连接
graph = Graph("bolt://localhost:7687", auth=("neo4j", "password"))

# 开始事务
# begin() 方法开始一个新事务
tx = graph.begin()

try:
    # 在事务中创建多个节点
    # 创建 100 个用户节点
    for i in range(100):
        # 创建节点对象
        node = Node("User", id=i, name=f"User_{i}")

        # 在事务中创建节点
        # create() 方法在事务中创建节点
        tx.create(node)

    # 提交事务
    # commit() 方法提交事务,所有操作才会真正执行
    tx.commit()
    print("✅ 批量创建成功!")

except Exception as e:
    # 如果出错,回滚事务
    # rollback() 方法回滚事务,取消所有操作
    tx.rollback()
    print(f"❌ 创建失败:{e}")

7.2 使用 UNWIND 优化批量操作 #

使用 Cypher 的 UNWIND 语句可以更高效地批量创建数据。

完整示例:

# 导入必要的类
from py2neo import Graph

# 创建数据库连接
graph = Graph("bolt://localhost:7687", auth=("neo4j", "password"))

# 准备批量数据
# 使用列表存储要创建的用户数据
users = [
    {"id": 1, "name": "张三", "age": 25},
    {"id": 2, "name": "李四", "age": 30},
    {"id": 3, "name": "王五", "age": 28}
]

# 使用 UNWIND 批量创建
# UNWIND 将列表展开为多行,然后批量处理
query = """
UNWIND $users AS user
MERGE (u:User {id: user.id})
SET u.name = user.name, u.age = user.age
RETURN u
"""

# 执行查询
# 将 users 列表作为参数传递
result = graph.run(query, users=users)

# 获取结果
data = result.data()
print(f"创建了 {len(data)} 个用户")

8. 小结 #

8.1 核心概念回顾 #

  • Graph:数据库连接对象
  • Node:节点对象,表示实体
  • Relationship:关系对象,表示节点之间的关联
  • NodeMatcher:节点匹配器,用于查询节点
  • 子图:节点和关系的集合

8.2 关键要点 #

  1. Py2neo 提供了 Pythonic 的 API,让图数据库操作更简单
  2. 使用 MERGE 可以避免重复创建节点和关系
  3. NodeMatcher 提供了类似 ORM 的查询接口
  4. 路径查询是图数据库的特色功能
  5. 使用事务可以提高批量操作的性能

8.3 下一步学习 #

掌握了 Py2neo 基础后,你可以:

  • 深入学习 Cypher 查询语言
  • 学习图算法(如最短路径、社区检测)
  • 探索 Neo4j 的高级功能
  • 在实际项目中应用图数据库

恭喜! 你已经掌握了 Py2neo 的基础知识。现在可以开始创建自己的图数据库应用了!

← 上一节 46.neo4j 下一节 48.Streamlit →

访问验证

请输入访问令牌

Token不正确,请重新输入