跳到主要内容

快速开始:建立图工程心智模型

延伸阅读

概念全景见 入门介绍;深入建模与 GraphRAG 见 开发指南

本章目标

读完并动手完成后,你应能:

  1. 用 NetworkX 或 Neo4j 创建带标签与属性的小图。
  2. 写出两跳模式匹配查询,并解释与 SQL JOIN 的差异。
  3. 运行 BFS/最短路径与简单中心性,读懂结果含义。
  4. 判断一个业务问题是否「值得上图」。

本篇聚焦知识与动手直觉,不涉及把 graph-engineering.chenxiaoshivivid.top 部署到生产环境。

0. 你需要什么环境

推荐两条并行路径(可任选其一先走通):

路径适合安装要点
Python + NetworkX算法直觉、教学原型pip install networkx matplotlib
Neo4j + Cypher持久化图、工业查询语法Neo4j Desktop 或 Docker 社区版

可选增强:py2neo / 官方 Python Driver、rdflib(RDF 入门)、torch-geometric(稍后再装)。

# 最小 Python 环境示例(使用虚拟环境)
python3 -m venv .venv
source .venv/bin/activate
pip install networkx matplotlib pandas

1. 十分钟:用 NetworkX 看见第一张图

import networkx as nx
import matplotlib.pyplot as plt

G = nx.DiGraph()
G.add_node("Alice", label="Person", city="Shanghai")
G.add_node("Bob", label="Person", city="Beijing")
G.add_node("Acme", label="Company", industry="AI")
G.add_edge("Alice", "Acme", type="WORKS_AT", since=2022)
G.add_edge("Bob", "Acme", type="WORKS_AT", since=2021)
G.add_edge("Alice", "Bob", type="KNOWS", weight=0.8)

print("节点数", G.number_of_nodes(), "边数", G.number_of_edges())
print("Alice 出边", list(G.out_edges("Alice", data=True)))
print("到 Acme 的最短路径", nx.shortest_path(G, "Alice", "Acme"))

观察三点:

  • 节点携带业务类型(Person/Company)与属性。
  • 有类型与属性(since、weight),关系是一等对象。
  • 有向图决定「Alice→Bob」与「Bob→Alice」是否同一关系。

练习:把「关注」建成双向两条边,再建成一条无向边,分别打印邻居集合,体会建模差异。

2. 十分钟:用 Cypher 表达同一模型

在 Neo4j Browser 中:

CREATE (a:Person {name:'Alice', city:'Shanghai'})
CREATE (b:Person {name:'Bob', city:'Beijing'})
CREATE (c:Company {name:'Acme', industry:'AI'})
CREATE (a)-[:WORKS_AT {since:2022}]->(c)
CREATE (b)-[:WORKS_AT {since:2021}]->(c)
CREATE (a)-[:KNOWS {weight:0.8}]->(b)
RETURN a, b, c;

查询「和 Alice 在同一公司的人」:

MATCH (a:Person {name:'Alice'})-[:WORKS_AT]->(c:Company)<-[:WORKS_AT]-(colleague:Person)
WHERE colleague <> a
RETURN colleague.name, c.name;

这是典型的模式匹配:你画出路径形状,引擎负责遍历。对比 SQL:你需要 employeescompanies 两表 JOIN,并自己保证「同一公司」条件不写错。

3. SQL vs Cypher:同一业务问题

电商「买了 A 的用户还买了什么」:

-- SQL:多层 JOIN,深度增加时复杂度陡增
SELECT DISTINCT p2.name
FROM orders o1
JOIN order_items oi1 ON oi1.order_id = o1.id
JOIN order_items oi2 ON oi2.order_id IN (
SELECT o2.id FROM orders o2 WHERE o2.user_id = o1.user_id
)
JOIN products p2 ON p2.id = oi2.product_id
WHERE o1.user_id = 42 AND oi2.product_id <> oi1.product_id;
// Cypher:路径即模式
MATCH (u:User {id: 42})-[:PURCHASED]->(p1:Product)
MATCH (u)-[:PURCHASED]->(p2:Product)
WHERE p2 <> p1
RETURN DISTINCT p2.name;

心智转换清单

  1. 先画 3–7 个节点的业务草图,再写查询。
  2. 边类型名用动词或动宾(PURCHASEDBELONGS_TO),避免含糊的 RELATED
  3. 深度可变时用 *1..3,并设上限,防止意外全图扫描。

4. 图论最小武器库(动手版)

4.1 遍历:BFS 与 DFS

from collections import deque

def bfs(graph, start):
seen, q = {start}, deque([start])
order = []
while q:
u = q.popleft()
order.append(u)
for v in graph.successors(u):
if v not in seen:
seen.add(v)
q.append(v)
return order

BFS 给最短无权路径;DFS 适合拓扑排序与连通分量探索。图数据库内部的路径扩展,本质上是受索引与方向约束的受限 BFS/DFS。

4.2 最短路径

path = nx.shortest_path(G, "Alice", "Bob")  # 无权
# 有权:nx.dijkstra_path(G, s, t, weight="weight")

社交「六度」查询在 Cypher 中:

MATCH (a:Person {name:'Alice'}), (b:Person {name:'Bob'})
MATCH p = shortestPath((a)-[:KNOWS*..6]-(b))
RETURN [n IN nodes(p) | n.name] AS route, length(p) AS hops;

务必限制 *..6:无上限的变长路径是生产事故高发区。

4.3 中心性直觉

指标直观含义何时用
度中心性直接邻居多少快速找枢纽
PageRank被重要节点指向权威排序、推荐种子
Betweenness有多少最短路径经过我桥接节点、风控切入点
Closeness到他人平均距离信息传播效率
print(nx.pagerank(G))
print(nx.degree_centrality(G))

先在 20 节点小图上肉眼验证「算法说的枢纽」是否符合业务直觉,再上万级图。

5. 第一个迷你知识图谱

场景:人物—任职—公司—位于—城市。

MERGE (alice:Person {name:'Alice'})
MERGE (acme:Company {name:'Acme'})
MERGE (sh:City {name:'Shanghai'})
MERGE (alice)-[:WORKS_AT {title:'Engineer'}]->(acme)
MERGE (acme)-[:LOCATED_IN]->(sh);

扩展问题:

  1. 「在上海工作的工程师有哪些?」——路径 Person-WORKS_AT->Company-LOCATED_IN->City
  2. 若同一公司有多个办公城市,LOCATED_IN 应挂在公司还是「办公地」事件节点?这是实体中心 vs 事件中心建模分歧。

建议:关系简单且稳定 → 实体中心;关系带时间、地点、角色且频繁变化 → 引入事件/事实节点。

6. 导入第一批 CSV(概念步骤)

  1. 准备 nodes_person.csvnodes_company.csvedges_works_at.csv
  2. 小数据用 LOAD CSV;百万级以上用批量导入工具(绕过逐条事务)。
  3. 导入后立刻跑:节点计数、边计数、度分布抽样、一条业务查询。
// 度分布抽样:找出超级节点苗头
MATCH (n)
RETURN labels(n)[0] AS label, n.name AS name, COUNT { (n)--() } AS degree
ORDER BY degree DESC LIMIT 20;

若 Top1 度远高于中位数,立刻记录,后续要做限流或边分片。

7. 查询优化入门:PROFILE

PROFILE
MATCH (a:Person {name:'Alice'})-[:KNOWS*1..3]-(b:Person)
RETURN DISTINCT b.name;

看执行计划是否:属性查找走索引、扩展方向合理、是否出现巨大中间结果。常见改进:

  • 为高频查找属性建索引:CREATE INDEX FOR (p:Person) ON (p.name);
  • 尽量带标签与边类型,避免全图 (n)--(m)
  • 参数化查询,禁止字符串拼接用户输入。

8. GraphRAG 最小闭环(本地思维实验)

不必先上完整平台,先用纸笔走通:

  1. 问题:「Alice 所在公司在哪座城市?」
  2. 实体链接:Alice → Person 节点。
  3. 子图扩展:WORKS_ATLOCATED_IN 两跳。
  4. 证据:「Alice-WORKS_AT->Acme-LOCATED_IN->Shanghai」。
  5. 生成:回答并引用路径。

对比纯向量:若语料里只有「Acme 很强」而没有城市事实,向量可能胡答;图路径则要么找到,要么明确「图中无此边」。

9. 七天课表如何对接本章

天数主题本章可预热的动作
Day1建模范式完成人物—公司图
Day2查询语言Cypher 两跳 + PROFILE
Day3图算法PageRank / 最短路径
Day4图库架构度分布与超级节点观察
Day5知识图谱MERGE + 属性约束
Day6GNN/GraphRAG证据路径打包思维实验
Day7生产与前沿导入校验与观测指标

子站 7 天学会 Graph Engineering 提供课表、算法沙盒与 SQL/Cypher 对比,建议与文档交叉阅读。

10. 验收清单(请自测)

  • 能口述节点、边、标签、属性、方向的区别。
  • 能写出至少一条 2 跳 Cypher,并解释结果。
  • 能对小图运行 BFS 与 PageRank,并解释 Top 节点。
  • 能指出一个「不该上图」的场景(例如纯报表聚合、无关系遍历)。
  • 能列出导入后必查的 4 个健康指标:点数、边数、度 Top、一条黄金查询。

11. 常见新手坑

  1. 把所有字段都做成节点:颜色、状态枚举优先做属性,除非要围绕它们做关系分析。
  2. 无类型的 RELATED 边:后期无法过滤与索引,查询会变成全图泥潭。
  3. 忽略方向FOLLOWS 画反会导致推荐与风控逻辑全部反转。
  4. 变长路径无上限:开发环境「碰巧很快」,生产直接超时。
  5. 只用可视化大屏验收:大屏好看不等于查询正确、证据可追溯。

12. 下一步

用一周时间每天做一个「垂直切片」:选一个真实小问题(通讯录、阅读书目、课程依赖),建图、查询、画路径、写三句结论。图工程的肌肉记忆,来自反复的「问题→模式→验证」,而不是只看术语表。

13. 小练习:社交媒体图(60 分钟)

设计并实现:

  • 节点:UserPostTag
  • 边:FOLLOWSPOSTEDLIKEDTAGGED_WITH

要求:

  1. 至少 10 用户、30 帖子、15 标签。
  2. 查询「我关注的人点赞过的帖子」三跳路径。
  3. 用度中心性找出「被关注最多」与「发帖最多」是否同一批人。
  4. 写 200 字笔记:哪些边该有时间戳属性?哪些查询会撞上超级网红节点?
MATCH (me:User {name:$me})-[:FOLLOWS]->(f)-[:LIKED]->(p:Post)
RETURN p.id, p.text, count(*) AS likesFromFollowing
ORDER BY likesFromFollowing DESC LIMIT 10;

FOLLOWS 出边巨大,先限制 f 数量或按最近活跃过滤——这就是生产级「超级节点治理」的雏形。

14. 从快速开始到工程判断

快速开始的终点不是「会跑通示例」,而是建立判断力:何时用属性、何时用节点;何时用图算法、何时用简单计数;何时上 GraphRAG、何时纯 Cypher 已够用。带着这些问题进入开发指南,你会读得更快、踩坑更少。