Py2neo 是一个用于连接和操作 Neo4j 图数据库的 Python 客户端库,提供了直观的 API 来执行 Cypher 查询和管理图数据。
1. Py2neo 核心特点 #
https://static.docs-hub.com/books_1753510587362.csv
- 官方推荐:Neo4j 官方推荐的 Python 驱动程序之一
- 多版本支持:兼容 Neo4j 3.x, 4.x 和 5.x 版本
- 多种操作方式:支持直接执行 Cypher 和 Pythonic 的对象操作
- 数据转换:自动将 Neo4j 数据转换为 Python 对象
- 事务支持:完整的事务管理功能
2. 安装与基本连接 #
2.1. 安装 #
下面的代码演示如何安装 py2neo 库。你只需在命令行中运行 pip 命令即可,无需在 Python 脚本中执行。
# 使用pip安装py2neo库
# 在命令行中运行:pip install py2neo2.2. 数据库连接 #
如何导入 py2neo 并连接本地 Neo4j 数据库。连接成功后可以进行后续所有操作。
# 导入py2neo库中的Graph类
from py2neo import Graph
# 连接到本地的Neo4j数据库,指定bolt协议、用户名和密码
graph = Graph("bolt://localhost:7687", auth=("neo4j", "12345678"))
# 打印连接对象,验证连接是否成功
print(graph)3. 数据模型基础 #
Py2neo 使用几种核心类表示图数据:
- Node - 节点/顶点
- Relationship - 关系/边
- Subgraph - 子图(节点和关系的集合)
- Path - 路径(连接的节点和关系序列)
3.1. 创建节点 #
如何创建带有标签和属性的节点对象。你可以为节点指定一个或多个标签,以及任意数量的属性。
# 导入py2neo库中的Node类
from py2neo import Node
# 创建一个标签为Person,属性为name=Alice, age=33的节点
person = Node("Person", name="Alice", age=33)
# 创建一个同时拥有Movie和Film两个标签,属性为title和year的节点
movie = Node("Movie", "Film", title="The Matrix", year=1999)
# 打印节点对象,查看其内容
print(person)
print(movie)3.2. 创建关系 #
如何在两个节点之间创建关系,并为关系添加属性。关系可以有方向和属性。
# 导入py2neo库中的Node和Relationship类
from py2neo import Node, Relationship
# 创建两个节点
person = Node("Person", name="Alice")
movie = Node("Movie", title="The Matrix")
# 创建一个person到movie的ACTED_IN关系,并添加roles属性
acted_in = Relationship(person, "ACTED_IN", movie, roles=["Neo"])
# 创建一个person到另一个人(Bob)的KNOWS关系,并添加since属性
bob = Node("Person", name="Bob")
knows = Relationship(person, "KNOWS", bob, since=2015)
# 打印关系对象,查看其内容
print(acted_in)
print(knows)4. 数据操作 #
4.1. 创建数据 #
如何将节点和关系写入Neo4j数据库。你可以单独写入节点、关系,也可以批量写入子图。
# 导入py2neo库中的Graph、Node、Relationship类
from py2neo import Graph, Node, Relationship
# 连接到本地Neo4j数据库
graph = Graph("bolt://localhost:7687", auth=("neo4j", "12345678"))
# 创建节点和关系
person = Node("Person", name="Alice")
movie = Node("Movie", title="The Matrix")
acted_in = Relationship(person, "ACTED_IN", movie, roles=["Neo"])
# 将单个节点写入数据库
graph.create(person)
# 将关系写入数据库(相关节点会自动写入)
graph.create(acted_in)
# 批量创建:将多个节点和关系合并为一个子图后一次性写入
subgraph = person | acted_in | movie
graph.create(subgraph)4.2. 查询数据 #
4.2.1. 基本查询 #
如何用Cypher语句查询节点,并遍历结果。适合需要灵活查询的场景。
# 导入py2neo库中的Graph类
from py2neo import Graph
# 连接到本地Neo4j数据库
graph = Graph("bolt://localhost:7687", auth=("neo4j", "12345678"))
# 执行Cypher查询,返回Person节点的name和age属性,最多5条
result = graph.run("MATCH (p:Person) RETURN p.name, p.age LIMIT 5")
# 遍历查询结果并打印
for record in result:
print(record["p.name"], record["p.age"])4.2.2. 参数化查询 #
如何使用参数化的Cypher查询,避免字符串拼接带来的安全风险。
# 导入py2neo库中的Graph类
from py2neo import Graph
# 连接到本地Neo4j数据库
graph = Graph("bolt://localhost:7687", auth=("neo4j", "12345678"))
# 使用参数化查询,查找name为Alice的Person节点
result = graph.run("MATCH (p:Person {name: $name}) RETURN p", name="Alice")
# 遍历结果并打印
for record in result:
print(record["p"])4.2.3. 对象查询 #
如何用NodeMatcher进行对象化查询。适合需要用Python对象方式操作图数据的场景。
# 导入py2neo库中的Graph和NodeMatcher类
from py2neo import Graph, NodeMatcher
# 连接到本地Neo4j数据库
graph = Graph("bolt://localhost:7687", auth=("neo4j", "12345678"))
# 创建NodeMatcher对象
matcher = NodeMatcher(graph)
# 查询第一个name为Alice的Person节点
alice = matcher.match("Person", name="Alice").first()
print(alice)
# 查询所有age大于等于30的Person节点,并按name排序
people = matcher.match("Person").where("_.age >= 30").order_by("_.name")
for person in people:
print(person)4.3. 更新数据 #
如何更新节点属性并推送到数据库。适合需要修改节点属性的场景。
# 导入py2neo库中的Graph和NodeMatcher类
from py2neo import Graph, NodeMatcher
# 连接到本地Neo4j数据库
graph = Graph("bolt://localhost:7687", auth=("neo4j", "12345678"))
# 查询name为Alice的节点
matcher = NodeMatcher(graph)
alice = matcher.match("Person", name="Alice").first()
# 修改节点属性
alice["age"] = 34
# 推送更改到数据库
graph.push(alice)4.4. 使用Cypher更新 #
如何用Cypher语句直接更新节点属性。适合批量或复杂更新场景。
# 导入py2neo库中的Graph类
from py2neo import Graph
# 连接到本地Neo4j数据库
graph = Graph("bolt://localhost:7687", auth=("neo4j", "12345678"))
# 用Cypher语句更新name为Alice的Person节点的age属性
graph.run("MATCH (p:Person {name: 'Alice'}) SET p.age = 35")4.5. 删除数据 #
如何删除节点和相关关系。可以用对象方式或Cypher语句删除。
# 导入py2neo库中的Graph和NodeMatcher类
from py2neo import Graph, NodeMatcher
# 连接到本地Neo4j数据库
graph = Graph("bolt://localhost:7687", auth=("neo4j", "12345678"))
# 查询name为Alice的节点
matcher = NodeMatcher(graph)
alice = matcher.match("Person", name="Alice").first()
# 删除节点(需先删除相关关系,否则会报错)
graph.delete(alice)
# 或者用Cypher语句删除节点及其所有关系
graph.run("MATCH (p:Person {name: 'Alice'}) DETACH DELETE p")5. 高级功能 #
5.1. 事务管理 #
如何使用显式事务进行多步操作。适合需要原子性操作的场景。
# 导入py2neo库中的Graph和Node类
from py2neo import Graph, Node
# 连接到本地Neo4j数据库
graph = Graph("bolt://localhost:7687", auth=("neo4j", "12345678"))
# 开始一个事务
tx = graph.begin()
try:
# 在事务中创建节点
node1 = Node("Person", name="Charlie")
tx.create(node1)
# 提交事务
graph.commit(tx)
except Exception as e:
# 如果出错则回滚事务
tx.rollback()
print("事务失败:", e)5.2. 批量操作 #
如何用Subgraph进行批量插入。适合一次性插入多个节点和关系。
# 导入py2neo库中的Graph、Node、Relationship和Subgraph类
from py2neo import Graph, Node, Relationship, Subgraph
# 连接到本地的Neo4j数据库,指定地址和认证信息
graph = Graph("bolt://localhost:7687", auth=("neo4j", "12345678"))
# 创建一个标签为Person,name为Tom的节点
node1 = Node("Person", name="Tom")
# 创建一个标签为Person,name为Jerry的节点
node2 = Node("Person", name="Jerry")
# 创建一个从Tom指向Jerry的KNOWS关系
rel = Relationship(node1, "KNOWS", node2)
# 构建一个包含上述两个节点和关系的子图
subgraph = Subgraph([node1, node2], [rel])
# 将子图写入到数据库中
graph.create(subgraph)5.3. 索引和约束 #
如何自动检测并删除已存在的索引和约束,然后再创建新的索引和唯一约束。这样可以避免重复创建导致的报错。
# 导入py2neo库
from py2neo import Graph
# 连接到本地Neo4j数据库
graph = Graph("bolt://localhost:7687", auth=("neo4j", "12345678"))
# 查询所有索引
indexes = graph.run("SHOW INDEXES").data()
# 遍历所有索引,删除与Person.name相关的索引
for idx in indexes:
# 判断索引是否是Person.name
if "Person" in str(idx.get("labelsOrTypes", "")) and "name" in str(
idx.get("properties", "")
):
# 获取索引名称
index_name = idx["name"]
print(f"删除索引: {index_name}")
graph.run(f"DROP INDEX {index_name}")
# 查询所有约束
constraints = graph.run("SHOW CONSTRAINTS").data()
for cons in constraints:
if "Person" in str(cons.get("labelsOrTypes", "")) and "email" in str(
cons.get("properties", "")
):
cons_name = cons["name"]
print(f"删除约束: {cons_name}")
graph.run(f"DROP CONSTRAINT {cons_name}")
# 创建索引
graph.run("CREATE INDEX person_name_index FOR (p:Person) ON (p.name)")
# 创建唯一约束
graph.run(
"CREATE CONSTRAINT person_email_unique FOR (p:Person) REQUIRE p.email IS UNIQUE"
)
6. 数据转换 #
6.1. 将查询结果转为Pandas DataFrame #
如何将Neo4j查询结果转为Pandas DataFrame,便于后续数据分析。
# 导入py2neo库和pandas库
from py2neo import Graph
import pandas as pd
graph = Graph("bolt://localhost:7687", auth=("neo4j", "12345678"))
# 执行查询,返回name和age
result = graph.run("MATCH (p:Person) RETURN p.name as name, p.age as age")
# 将结果转为DataFrame
df = pd.DataFrame(result.data())
# 打印DataFrame
print(df)
6.2. 从DataFrame导入数据 #
如何将Pandas DataFrame中的数据批量导入Neo4j数据库。
# 导入py2neo库中的Graph、Node和Subgraph类
from py2neo import Graph, Node, Subgraph
# 导入pandas库用于数据处理
import pandas as pd
# 连接到本地的Neo4j数据库,指定地址和认证信息
graph = Graph("bolt://localhost:7687", auth=("neo4j", "12345678"))
# 创建一个包含两个人信息的DataFrame
df = pd.DataFrame([{"name": "David", "age": 40}, {"name": "Eva", "age": 28}])
# 将DataFrame的每一行转换为一个Person节点
nodes = [Node("Person", **row) for row in df.to_dict("records")]
# 创建一个只包含这些节点的子图
subgraph = Subgraph(nodes)
# 将子图写入到Neo4j数据库中
graph.create(subgraph)
7. 学习资源 #
- 官方文档:https://py2neo.org/
- Neo4j Cypher手册:https://neo4j.com/docs/cypher-manual/current/
- GitHub仓库:https://github.com/neo4j-contrib/neo4j-python-driver
Py2neo 提供了与 Neo4j 交互的 Pythonic 方式,适合需要在 Python 生态中进行图数据操作的场景。相比官方的 neo4j-driver,Py2neo 提供了更高级的抽象和更方便的对象操作接口。