抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

摘要:本文主要学习了如何使用聚合查询,包括管道操作符和聚合操作符的使用。

环境

Windows 10 企业版 LTSC 21H2
MongoDB 6.0.21

1 介绍

聚合是将复杂的查询分解为多个阶段,每个阶段使用操作符定义操作方式,最后将所有的阶段聚合形成结果并返回。

操作符分为管道操作符和聚合操作符,管道操作符定义阶段,聚合操作符需要在特定的管道操作符中使用,得到相应的聚合结果。

2 规范

语法:

bson
1
db.集合名.aggregate(pipeline)

含义:

名称 类型 说明
pipeline 文档或数组 由操作符组成的多个阶段。

3 使用

3.1 管道操作符

3.1.1 match

用于过滤文档,只允许匹配条件的文档通过。

根据查询条件过滤文档:

bson
1
{ $match: <query> }

含义:

名称 类型 说明
query 文档 要查询的文档,支持通过查询操作符匹配,不支持聚合操作符匹配。如果需要支持聚合操作符匹配,应该在$expr中使用。

查询age属性等于25的文档:

bson
1
db.student.aggregate({ $match: { age: { $eq: 25 } } });

等价于:

bson
1
db.student.find({ age: { $eq: 25 } });

3.1.2 project

用于定制返回结果,指定返回的属性,支持别名。

根据规则定制返回结果:

bson
1
{ $project: <projections> }

含义:

名称 类型 说明
projections 文档 返回属性的规则,支持包含和排除,以及重命名。

查询name属性,并排除_id属性:

bson
1
db.student.aggregate({ $project: { _id: 0, name: 1 } });

查询name属性和addr属性,并将addr属性重命名为address属性:

bson
1
2
db.student.aggregate({ $project: { _id: 0, name: 1, address: "$addr" } }
);

3.1.3 sort

用于对文档进行排序。

根据规则对文档进行排序:

bson
1
{ $sort: <rules> }

含义:

名称 类型 说明
rules 文档 排序规则,使用键值对形式。

查询文档,按age属性和sex属性排序并返回:

bson
1
db.student.aggregate({ $sort: { age: 1, sex: 1 } });

等价于:

bson
1
2
db.student.find()
.sort({ age: 1, sex: 1 });

3.1.4 skip

用于跳过指定数量的文档。

跳过指定数量的文档:

bson
1
{ $skip: <skipNum> }

含义:

名称 类型 说明
skipNum 整型 跳过的文档数量。

跳过前2条文档:

bson
1
db.student.aggregate({ $skip: 2 });

等价于:

bson
1
2
db.student.find()
.skip(2);

3.1.5 limit

用于查询指定数量的文档。

查询指定数量的文档:

bson
1
{ $limit: <limitNum> }

含义:

名称 类型 说明
limitNum 整型 查询的文档数量。

查询前2条文档:

bson
1
db.student.aggregate({ $limit: 2 });

等价于:

bson
1
2
db.student.find()
.limit(2);

3.1.6 count

用于统计查询的文档数量。

统计查询的文档数量:

bson
1
{ $count: <countName> }

含义:

名称 类型 说明
countName 字符串 输出的统计名称。

统计查询的文档数量,并将count作为名称返回:

bson
1
db.student.aggregate({ $count: "count" });

3.1.7 group

用于对文档分组,并执行聚合操作。

统计查询的文档数量:

bson
1
2
3
4
5
6
{
$group: {
_id: <expression>,
<field>: { <operator>: <expression> }
}
}

含义:

名称 类型 说明
field 属性 可选。返回的属性,可以有多个。
operator 操作符 通过操作符处理返回的属性。
expression 字符串或文档 用于操作符处理的表达式。
使用$属性的方式指定属性。

对文档分组,统计数量:

bson
1
2
3
4
5
6
db.student.aggregate({
$group: {
_id: null,
count: { $count: {} }
}
});

对文档按sex属性分组,统计文档数量:

bson
1
2
3
4
5
6
db.student.aggregate({
$group: {
_id: "$sex",
sexCount: { $count: {} }
}
});

$group中使用的$count是聚合操作符,并不是管道操作符。

3.1.8 lookup

用于将多个集合中的文档关联查询。

3.1.8.1 单个条件

单个条件的关联查询:

bson
1
2
3
4
5
6
7
8
{
$lookup: {
from: <collectionName>,
localField: <localFieldName>,
foreignField: <foreignFieldName>,
as: <asName>
}
}

含义:

名称 类型 说明
collectionName 字符串 同一个数据库中的关联集合。
localFieldName 字符串 本地集合中的属性,用于同关联集合中的属性关联。
foreignFieldName 字符串 关联集合中的属性,用于同本地集合中的属性关联。
asName 字符串 返回的属性名。

单个条件的关联查询,将学校信息关联到学生信息表:

bson
1
2
3
4
5
6
7
8
db.student.aggregate({
$lookup: {
from: "school",
localField: "school",
foreignField: "_id",
as: "schoolInfo"
}
});

将学校信息关联到学生信息表:

bson
1
2
3
4
5
6
7
8
9
10
11
12
13
14
{
"_id": 1,
"name": "张三",
"sex": "男",
"addr": "北京市 东城区",
"age": 25,
"expenditure": 80,
"income": 100,
"school": 2,
"total": 720,
"schoolInfo": [
{ "_id": 2, "name": "北京大学", "score": 700 }
]
}
3.1.8.2 多个条件

多个条件的关联查询:

bson
1
2
3
4
5
6
7
8
{
$lookup: {
from: <collectionName>,
let: { <localName>: <localFieldName> },
pipeline: [ <operator>: <expression> ],
as: <asName>
}
}

含义:

名称 类型 说明
collectionName 字符串 同一个数据库中的关联集合。
let 文档 本地集合中的属性,可以有多个。
localName 字符串 本地集合中的属性别名。
localFieldName 字符串 本地集合中的属性别名对应的本地属性。
使用$属性的方式指定本地集合属性。
pipeline 数组 关联集合中的属性,使用管道操作符关联本地集合和关联集合,可以有多个。
operator 操作符 通过操作符处理返回的属性。
expression 字符串或文档 用于操作符处理的表达式。
使用$属性的方式指定关联集合属性,使用$$属性的方式指定本地集合属性别名。
asName 字符串 返回的属性名。

多个条件的关联查询,将学校信息关联到学生信息表,并查询学生总分超过学校分数的文档:

bson
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
db.student.aggregate({
$lookup: {
from: "school",
let: { stuSchool: "$school", stuTotal: "$total" },
pipeline: [
{ $match:
{ $expr:
{ $and: [
{ $eq: [ "$_id", "$$stuSchool" ] },
{ $lte: [ "$score", "$$stuTotal" ] }
] }
}
}
],
as: "schoolInfo"
}
});

将学校信息关联到学生信息表,并查询学生总分超过学校分数的文档:

bson
1
2
3
4
5
6
7
8
9
10
11
12
13
14
{
"_id": 1,
"name": "张三",
"sex": "男",
"addr": "北京市 东城区",
"age": 25,
"expenditure": 80,
"income": 100,
"school": 2,
"total": 720,
"schoolInfo": [
{ "_id": 2, "name": "北京大学", "score": 700 }
]
}

3.2 聚合操作符

3.2.1 count

统计文档的数量。

统计数量不需要使用参数:

bson
1
{ $count: {} }

对文档按sex属性分组,统计文档数量:

bson
1
2
3
4
5
6
db.student.aggregate({
$group: {
_id: "$sex",
sexCount: { $count: {} }
}
});

3.2.2 sum

计算并返回数字的总和。

$project中对数组属性求和,或者在$group中对数字属性求和:

bson
1
{ $sum: <expression> }

$project中对数组属性求和:

bson
1
{ $sum: [ <expression>, <expression> ] }

含义:

名称 类型 说明
expression 数字或属性 使用$属性的方式指定属性,忽略非数字的属性值。

对文档按sex属性分组,统计文档数量并计算age属性的总和:

bson
1
2
3
4
5
6
7
db.student.aggregate({
$group: {
_id: "$sex",
sexCount: { $count: {} },
sexSumAge: { $sum: "$age" }
}
});

统计文档scores数组的总和作为totalScore属性返回,只显示name属性和totalScore属性:

bson
1
2
3
4
5
6
7
db.student.aggregate({
$project: {
_id: 0,
name: 1,
totalScore: { $sum: "$scores" }
}
});

3.2.3 avg

计算并返回数字的平均值。

$project中对数组属性求平均值,或者在$group中对数字属性求平均值:

bson
1
{ $avg: <expression> }

$project中对数组属性求平均值:

bson
1
{ $avg: [ <expression>, <expression> ] }

含义:

名称 类型 说明
expression 数字或属性 使用$属性的方式指定属性,忽略非数字的属性值。

对文档按sex属性分组,统计文档数量并计算age属性的平均值:

bson
1
2
3
4
5
6
7
db.student.aggregate({
$group: {
_id: "$sex",
sexCount: { $count: {} },
sexAvgAge: { $avg: "$age" }
}
});

统计文档scores数组的平均值作为meanScore属性返回,只显示name属性和meanScore属性:

bson
1
2
3
4
5
6
7
db.student.aggregate({
$project: {
_id: 0,
name: 1,
meanScore: { $avg: "$scores" }
}
});

3.2.4 cond

条件表达式,根据条件执行表达式。

根据条件执行表达式:

bson
1
2
3
4
5
6
7
{
$cond: {
if: <expression>,
then: <trueCase>,
else: <falseCase>
}
}

含义:

名称 类型 说明
expression 文档 计算结果为布尔类型的表达式。
trueCase 文档 计算结果为true时返回此表达式的结果。
falseCase 文档 计算结果为false时返回此表达式的结果。

统计文档scores数组的总和,根据是否超过250作为level属性,返回name属性和level属性:

bson
1
2
3
4
5
6
7
8
9
10
11
12
13
db.student.aggregate({
$project: {
_id: 0,
name: 1,
level: {
$cond: {
if: { $gt: [ { $sum: "$scores" }, 250 ] },
then: "尖子生",
else: "普通生"
}
}
}
});

评论