mongodb视图的使用

为什么要用视图,或者说什么情况下用视图?
  1. 简化查询:对于多个聚合查询,可以抽象出同一个视图,简化查询语句。
  2. 数据安全:源集合有些字段不想暴露出去,通过视图简化集合字段,只暴露视图给外部。
下面举个简单的例子:
1. 首先创建两个集合c1、c2,并插入一些数据:
1
2
3
4
5
6
7
8
9
10
11
db.c1.insertMany([
{k:1, v:1},
{k:2, v:2},
{k:3, v:3}
]);

db.c2.insertMany([
{k:1, v:4},
{k:3, v:5},
{k:3, v:6}
]);
2. 然后创建视图v1,使用c1作为主表,c2为级联表,k为关联字段:
1
2
3
4
5
6
7
8
9
10
11
12
13
db.createView(
"v1", // 视图名
"c1", // 主表名
[ // pipeline
{
$lookup: { // 级联
from:"c2", // 级联表名
localField:"k", // c1关联字段
foreignField:"k", // c2关联字段
as:"child" // c2在视图中的别名
}
}
]);

查询v1视图,可以得到树形结构的级联数据

3. 如果想把树形级联转为笛卡尔积,就要展开child字段:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
db.v1.drop();
db.createView(
"v1", // 视图名
"c1", // 主表名
[ // pipeline
{
$lookup: { // 级联
from: "c2", // 级联表名
localField: "k", // c1关联字段
foreignField: "k", // c2关联字段
as: "child" // c2在视图中的别名
}
},
{
$unwind: { // 展开数组
path: "$child", // 要展开的数组字段
preserveNullAndEmptyArrays: true // 数组为空时,保留上级记录(类似left join);默认false(类似inner join)
}
}
]);

再查询v1视图,可以看到 k=3 的记录展开为2条了

4. child还是个object类型,不太直观,做个字段映射:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
db.v1.drop();
db.createView(
"v1", // 视图名
"c1", // 主表名
[ // pipeline
{
$lookup: { // 级联
from: "c2", // 级联表名
localField: "k", // c1关联字段
foreignField: "k", // c2关联字段
as: "child" // c2在视图中的别名
}
},
{
$unwind: { // 展开数组
path: "$child", // 要展开的数组字段
preserveNullAndEmptyArrays: true // 数组为空时,保留上级记录(类似left join);默认false(类似inner join)
}
},
{
$project: { // 视图字段名,类似select
_id: 0, // 去掉_id字段,默认保留
k: 1, // 主表k字段
c1_v: "$v", // 主表v字段,在视图中别名c1_v
c2_v: "$child.v" // 子表v字段,在视图中别名c2_v
}
}
]);

再查询v1视图,达到最终想要的结果了: