Neo4j 基础教程(三):数据建模与程序连接实战
Neo4j 基础教程(三):数据建模与程序连接实战
环境:macOS + Neo4j + Python
Part 1:数据建模最佳实践
建模原则
原则一:按业务语义建模,而非表结构
图数据库的优势在于关系,先想清楚「是什么」和「如何关联」。
| 场景 | 节点标签 | 关系类型 | 关键属性 |
|---|---|---|---|
| 社交网络 | :User |
:FOLLOWS |
since |
| 电商 | :Product, :Customer |
:PURCHASED |
quantity, date |
| 推荐系统 | :User, :Item |
:RATED |
score |
| 组织架构 | :Employee |
:REPORTS_TO |
since |
关系方向的设计
- 有天然方向:
REPORTS_TO(有向) - 双向均可查询:
[:KNOWS]可两端 MATCH - 无方向:属性关系如
MATCH (a)-[r:distance {km: 100}]-(b)
建模示例:电影推荐系统
// 创建电影数据模型
CREATE(u1:User {name: '张三', age: 28}),(u2:User {name: '李四', age: 35}),(m1:Movie {title: '流浪地球', genre: '科幻', rating: 8.5}),(m2:Movie {title: '满江红', genre: '悬疑', rating: 7.8}),(a1:Actor {name: '吴京', country: '中国'}),(a2:Actor {name: '沈腾', country: '中国'});MATCH (m1:Movie {title:'流浪地球'}), (a1:Actor {name:'吴京'}) CREATE (a1)-[:ACTED_IN]->(m1);
MATCH (m2:Movie {title:'满江红'}), (a2:Actor {name:'沈腾'}) CREATE (a2)-[:ACTED_IN]->(m2);
MATCH (u1:User {name:'张三'}), (m1:Movie {title:'流浪地球'}) CREATE (u1)-[:RATED {score: 9}]->(m1);
MATCH (u1:User {name:'张三'}), (m2:Movie {title:'满江红'}) CREATE (u1)-[:RATED {score: 6}]->(m2);
MATCH (u2:User {name:'李四'}), (m1:Movie {title:'流浪地球'}) CREATE (u2)-[:RATED {score: 8}]->(m1);
查询示例:给用户推荐电影
// 找到张三喜欢的演员主演但张三还没看过的电影
MATCH (u:User {name: '张三'})-[:RATED {score: 8}]->(m:Movie)<-[:ACTED_IN]-(a:Actor)
WHERE NOT (u)-[:RATED]->(m)
RETURN m.title AS 推荐电影, a.name AS 主演, m.rating AS 评分
ORDER BY m.rating DESC
Part 2:Python 连接 Neo4j(neo4j-driver)
安装驱动
pip install neo4j
连接数据库
from neo4j import GraphDatabaseclass Neo4jConnection:def __init__(self, uri, user, password):self.driver = GraphDatabase.driver(uri, auth=(user, password))def close(self):self.driver.close()def query(self, cypher, parameters=None):with self.driver.session() as session:result = session.run(cypher, parameters)return [dict(record) for record in result]# 连接(Docker 默认地址)
conn = Neo4jConnection(uri="bolt://localhost:7687",user="neo4j",password="password"
)
完整示例:增删改查
# ========== 写入数据 ==========
def create_user(conn, name, age):cypher = """MERGE (u:User {name: $name})SET u.age = $ageRETURN u"""result = conn.query(cypher, {"name": name, "age": age})print(f"创建用户: {result[0]['u']['name']}")create_user(conn, "王五", 30)# ========== 查询数据 ==========
def find_friends(conn, user_name):cypher = """MATCH (u:User {name: $name})-[:KNOWS]->(friend)RETURN friend.name AS name, friend.age AS age"""return conn.query(cypher, {"name": user_name})friends = find_friends(conn, "Alice")
for f in friends:print(f"好友: {f['name']}, 年龄: {f['age']}")# ========== 事务写入 ==========
def create_relationship(conn, from_name, to_name, rel_type):cypher = f"""MATCH (a:User {{name: $from}}), (b:User {{name: $to}})MERGE (a)-[:{rel_type}]->(b)"""conn.query(cypher, {"from": from_name, "to": to_name})print(f"创建关系: {from_name} -> {to_name}")create_relationship(conn, "Bob", "Carol", "KNOWS")conn.close()
推荐学习路径
第1天:安装 Neo4j,熟悉 Browser 操作 → 教程一
第2天:掌握 Cypher CRUD → 教程二
第3天:设计自己的数据模型,写 Python 连接
常用资源
- Neo4j Cypher 官方文档
- Neo4j Python Driver
- Neo4j Browser 快捷键
三篇教程已完成!涵盖:安装入门 → Cypher 查询 → 数据建模与代码连接
---------------------------------------------------------------
来自博客园的aspnetx宋卫东
