图数据库概念 #
一、图数据库概述 #
图数据库是一种以图结构存储和查询数据的数据库,由顶点(Vertex)和边(Edge)组成。
1.1 图结构 #
text
┌─────────────────────────────────────────────────────────┐
│ 图结构示例 │
├─────────────────────────────────────────────────────────┤
│ │
│ ┌───────┐ 关注 ┌───────┐ 关注 ┌───────┐ │
│ │ 用户A │────────▶│ 用户B │────────▶│ 用户C │ │
│ └───────┘ └───────┘ └───────┘ │
│ │ │ │
│ │ 购买 │ 评论 │
│ ▼ ▼ │
│ ┌───────┐ ┌───────┐ │
│ │ 商品D │ │ 文章E │ │
│ └───────┘ └───────┘ │
│ │
│ 顶点(Vertex) = 实体 边(Edge) = 关系 │
└─────────────────────────────────────────────────────────┘
1.2 核心概念 #
| 概念 | 说明 | 对应集合 |
|---|---|---|
| 顶点(Vertex) | 图中的实体节点 | 文档集合 |
| 边(Edge) | 连接顶点的关系 | 边集合 |
| 图(Graph) | 顶点和边的集合 | 图定义 |
1.3 图数据库优势 #
| 优势 | 说明 |
|---|---|
| 关系表达 | 天然表达实体间关系 |
| 高效遍历 | 快速查询多跳关系 |
| 灵活扩展 | 轻松添加新的关系类型 |
| 直观建模 | 接近现实世界的建模方式 |
二、顶点(Vertex) #
2.1 顶点定义 #
顶点是图中的实体节点,存储实体的属性信息:
json
{
"_key": "user_001",
"_id": "users/user_001",
"name": "张三",
"email": "zhangsan@example.com",
"age": 28
}
2.2 顶点集合 #
顶点存储在普通的文档集合中:
javascript
db._create("users");
db._create("products");
db._create("posts");
2.3 顶点类型 #
text
社交网络图
├── 用户顶点
│ ├── 用户A
│ ├── 用户B
│ └── 用户C
├── 商品顶点
│ ├── 商品1
│ └── 商品2
└── 文章顶点
├── 文章1
└── 文章2
三、边(Edge) #
3.1 边定义 #
边连接两个顶点,表示它们之间的关系:
json
{
"_key": "follow_001",
"_id": "follows/follow_001",
"_from": "users/user_001",
"_to": "users/user_002",
"createdAt": "2024-01-15T10:30:00Z",
"type": "friend"
}
3.2 边属性 #
| 属性 | 说明 |
|---|---|
| _from | 边的起点顶点_id |
| _to | 边的终点顶点_id |
| 其他属性 | 关系的附加信息 |
3.3 边集合 #
边存储在边集合中:
javascript
db._createEdgeCollection("follows");
db._createEdgeCollection("purchased");
db._createEdgeCollection("commented");
3.4 边的方向 #
text
有向边:
用户A ──关注──▶ 用户B
_from: "users/userA"
_to: "users/userB"
3.5 边类型 #
text
社交网络边类型
├── 关注关系
│ └── 用户A 关注 用户B
├── 购买关系
│ └── 用户A 购买 商品1
├── 评论关系
│ └── 用户A 评论 文章1
└── 好友关系
└── 用户A 好友 用户B
四、图定义 #
4.1 创建图 #
JavaScript创建:
javascript
var graph = db._createGraph("social", {
edgeDefinitions: [
{
collection: "follows",
from: ["users"],
to: ["users"]
},
{
collection: "purchased",
from: ["users"],
to: ["products"]
}
]
});
4.2 图结构 #
json
{
"name": "social",
"edgeDefinitions": [
{
"collection": "follows",
"from": ["users"],
"to": ["users"]
}
],
"orphanCollections": []
}
4.3 边定义 #
边定义指定了边集合可以连接的顶点集合:
javascript
{
collection: "follows",
from: ["users"],
to: ["users"]
}
4.4 查看图 #
javascript
db._graphs.toArray();
4.5 删除图 #
javascript
db._graph("social").drop();
五、图遍历 #
5.1 遍历方向 #
| 方向 | 说明 |
|---|---|
| OUTBOUND | 从_from到_to方向 |
| INBOUND | 从_to到_from方向 |
| ANY | 双向遍历 |
5.2 遍历语法 #
aql
FOR v, e, p IN min..max DIRECTION startVertex edgeCollection
RETURN { vertex: v, edge: e, path: p }
5.3 遍历变量 #
| 变量 | 说明 |
|---|---|
| v | 当前顶点 |
| e | 当前边 |
| p | 完整路径 |
5.4 路径结构 #
json
{
"vertices": [
{ "_id": "users/user_001", "name": "张三" },
{ "_id": "users/user_002", "name": "李四" }
],
"edges": [
{ "_id": "follows/follow_001", "type": "friend" }
]
}
六、图遍历示例 #
6.1 一跳遍历 #
查找用户A关注的人:
aql
FOR v IN 1..1 OUTBOUND "users/user_001" follows
RETURN v.name
6.2 多跳遍历 #
查找用户A的朋友的朋友:
aql
FOR v IN 2..2 OUTBOUND "users/user_001" follows
RETURN v.name
6.3 范围遍历 #
查找1-3跳内的所有用户:
aql
FOR v, e, p IN 1..3 OUTBOUND "users/user_001" follows
RETURN {
name: v.name,
depth: LENGTH(p.edges),
path: p.vertices[*].name
}
6.4 双向遍历 #
查找用户A的所有关注者和被关注者:
aql
FOR v, e IN ANY "users/user_001" follows
RETURN {
name: v.name,
direction: e._from == "users/user_001" ? "following" : "follower"
}
6.5 入边遍历 #
查找关注用户A的人:
aql
FOR v IN 1..1 INBOUND "users/user_001" follows
RETURN v.name
七、图查询进阶 #
7.1 带过滤的遍历 #
aql
FOR v, e, p IN 1..3 OUTBOUND "users/user_001" follows
FILTER v.status == "active"
FILTER e.type == "friend"
RETURN v.name
7.2 带限制的遍历 #
aql
FOR v IN 1..2 OUTBOUND "users/user_001" follows
LIMIT 10
RETURN v.name
7.3 路径去重 #
aql
FOR v, e, p IN 1..3 OUTBOUND "users/user_001" follows
OPTIONS { uniqueVertices: "global" }
RETURN v.name
7.4 遍历选项 #
| 选项 | 说明 |
|---|---|
| uniqueVertices | 顶点去重策略 |
| uniqueEdges | 边去重策略 |
| bfs | 广度优先搜索 |
| parallelism | 并行度 |
7.5 广度优先搜索 #
aql
FOR v IN 1..3 OUTBOUND "users/user_001" follows
OPTIONS { bfs: true, uniqueVertices: "global" }
RETURN v.name
八、图算法 #
8.1 最短路径 #
aql
FOR v, e IN OUTBOUND K_SHORTEST_PATHS "users/user_001" TO "users/user_005" follows
RETURN {
vertices: v,
edges: e
}
8.2 全对最短路径 #
aql
FOR source IN users
FOR target IN users
FILTER source._key != target._key
LET path = (
FOR v, e IN OUTBOUND K_SHORTEST_PATHS source TO target follows
LIMIT 1
RETURN LENGTH(e)
)[0]
RETURN {
from: source.name,
to: target.name,
distance: path
}
8.3 k-shortest路径 #
aql
FOR p IN OUTBOUND K_PATHS "users/user_001" TO "users/user_005" follows
LIMIT 3
RETURN p
九、图数据库应用场景 #
9.1 社交网络 #
text
社交网络图
├── 顶点
│ ├── 用户
│ ├── 群组
│ └── 话题
└── 边
├── 关注
├── 加入
└── 发布
9.2 知识图谱 #
text
知识图谱
├── 顶点
│ ├── 概念
│ ├── 实体
│ └── 属性
└── 边
├── 是一种
├── 包含
└── 相关
9.3 推荐系统 #
text
推荐系统图
├── 顶点
│ ├── 用户
│ ├── 商品
│ └── 标签
└── 边
├── 购买
├── 浏览
└── 标记
9.4 欺诈检测 #
text
欺诈检测图
├── 顶点
│ ├── 账户
│ ├── 设备
│ └── 交易
└── 边
├── 使用
├── 转账
└── 关联
十、图设计最佳实践 #
10.1 顶点设计 #
text
原则:
├── 顶点代表实体
├── 属性存储实体信息
├── 避免过度嵌套
└── 合理设置_id
10.2 边设计 #
text
原则:
├── 边代表关系
├── 方向要有意义
├── 属性存储关系信息
└── 合理命名边类型
10.3 索引设计 #
javascript
db.follows.ensureHashIndex(["_from"]);
db.follows.ensureHashIndex(["_to"]);
10.4 性能优化 #
text
优化建议:
├── 限制遍历深度
├── 使用过滤条件
├── 设置遍历选项
└── 合理使用索引
十一、总结 #
图数据库核心概念:
- 顶点:图中的实体节点
- 边:连接顶点的关系
- 图:顶点和边的集合
- 遍历:在图中导航查询
- 方向:OUTBOUND、INBOUND、ANY
下一步,让我们学习边集合与顶点操作!
最后更新:2026-03-27