摘要:本文主要学习了如何使用聚合查询,包括管道操作符和聚合操作符的使用。
环境
Windows 10 企业版 LTSC 21H2
MongoDB 6.0.21
1 介绍
聚合是将复杂的查询分解为多个阶段,每个阶段使用操作符定义操作方式,最后将所有的阶段聚合形成结果并返回。
操作符分为管道操作符和聚合操作符,管道操作符定义阶段,聚合操作符需要在特定的管道操作符中使用,得到相应的聚合结果。
2 规范
语法:
1 | db.集合名.aggregate(pipeline) |
含义:
名称 | 类型 | 说明 |
---|---|---|
pipeline | 文档或数组 | 由操作符组成的多个阶段。 |
3 使用
3.1 管道操作符
3.1.1 match
用于过滤文档,只允许匹配条件的文档通过。
根据查询条件过滤文档:
1 | { $match: <query> } |
含义:
名称 | 类型 | 说明 |
---|---|---|
query | 文档 | 要查询的文档,支持通过查询操作符匹配,不支持聚合操作符匹配。如果需要支持聚合操作符匹配,应该在$expr 中使用。 |
查询age属性等于25的文档:
1 | db.student.aggregate({ $match: { age: { $eq: 25 } } }); |
等价于:
1 | db.student.find({ age: { $eq: 25 } }); |
3.1.2 project
用于定制返回结果,指定返回的属性,支持别名。
根据规则定制返回结果:
1 | { $project: <projections> } |
含义:
名称 | 类型 | 说明 |
---|---|---|
projections | 文档 | 返回属性的规则,支持包含和排除,以及重命名。 |
查询name属性,并排除_id属性:
1 | db.student.aggregate({ $project: { _id: 0, name: 1 } }); |
查询name属性和addr属性,并将addr属性重命名为address属性:
1 | db.student.aggregate({ $project: { _id: 0, name: 1, address: "$addr" } } |
3.1.3 sort
用于对文档进行排序。
根据规则对文档进行排序:
1 | { $sort: <rules> } |
含义:
名称 | 类型 | 说明 |
---|---|---|
rules | 文档 | 排序规则,使用键值对形式。 |
查询文档,按age属性和sex属性排序并返回:
1 | db.student.aggregate({ $sort: { age: 1, sex: 1 } }); |
等价于:
1 | db.student.find() |
3.1.4 skip
用于跳过指定数量的文档。
跳过指定数量的文档:
1 | { $skip: <skipNum> } |
含义:
名称 | 类型 | 说明 |
---|---|---|
skipNum | 整型 | 跳过的文档数量。 |
跳过前2条文档:
1 | db.student.aggregate({ $skip: 2 }); |
等价于:
1 | db.student.find() |
3.1.5 limit
用于查询指定数量的文档。
查询指定数量的文档:
1 | { $limit: <limitNum> } |
含义:
名称 | 类型 | 说明 |
---|---|---|
limitNum | 整型 | 查询的文档数量。 |
查询前2条文档:
1 | db.student.aggregate({ $limit: 2 }); |
等价于:
1 | db.student.find() |
3.1.6 count
用于统计查询的文档数量。
统计查询的文档数量:
1 | { $count: <countName> } |
含义:
名称 | 类型 | 说明 |
---|---|---|
countName | 字符串 | 输出的统计名称。 |
统计查询的文档数量,并将count作为名称返回:
1 | db.student.aggregate({ $count: "count" }); |
3.1.7 group
用于对文档分组,并执行聚合操作。
统计查询的文档数量:
1 | { |
含义:
名称 | 类型 | 说明 |
---|---|---|
field | 属性 | 可选。返回的属性,可以有多个。 |
operator | 操作符 | 通过操作符处理返回的属性。 |
expression | 字符串或文档 |
用于操作符处理的表达式。 使用 $属性 的方式指定属性。 |
对文档分组,统计数量:
1 | db.student.aggregate({ |
对文档按sex属性分组,统计文档数量:
1 | db.student.aggregate({ |
在$group
中使用的$count
是聚合操作符,并不是管道操作符。
3.1.8 lookup
用于将多个集合中的文档关联查询。
3.1.8.1 单个条件
单个条件的关联查询:
1 | { |
含义:
名称 | 类型 | 说明 |
---|---|---|
collectionName | 字符串 | 同一个数据库中的关联集合。 |
localFieldName | 字符串 | 本地集合中的属性,用于同关联集合中的属性关联。 |
foreignFieldName | 字符串 | 关联集合中的属性,用于同本地集合中的属性关联。 |
asName | 字符串 | 返回的属性名。 |
单个条件的关联查询,将学校信息关联到学生信息表:
1 | db.student.aggregate({ |
将学校信息关联到学生信息表:
1 | { |
3.1.8.2 多个条件
多个条件的关联查询:
1 | { |
含义:
名称 | 类型 | 说明 |
---|---|---|
collectionName | 字符串 | 同一个数据库中的关联集合。 |
let | 文档 | 本地集合中的属性,可以有多个。 |
localName | 字符串 | 本地集合中的属性别名。 |
localFieldName | 字符串 |
本地集合中的属性别名对应的本地属性。 使用 $属性 的方式指定本地集合属性。 |
pipeline | 数组 | 关联集合中的属性,使用管道操作符关联本地集合和关联集合,可以有多个。 |
operator | 操作符 | 通过操作符处理返回的属性。 |
expression | 字符串或文档 |
用于操作符处理的表达式。 使用 $属性 的方式指定关联集合属性,使用$$属性 的方式指定本地集合属性别名。 |
asName | 字符串 | 返回的属性名。 |
多个条件的关联查询,将学校信息关联到学生信息表,并查询学生总分超过学校分数的文档:
1 | db.student.aggregate({ |
将学校信息关联到学生信息表,并查询学生总分超过学校分数的文档:
1 | { |
3.2 聚合操作符
3.2.1 count
统计文档的数量。
统计数量不需要使用参数:
1 | { $count: {} } |
对文档按sex属性分组,统计文档数量:
1 | db.student.aggregate({ |
3.2.2 sum
计算并返回数字的总和。
在$project
中对数组属性求和,或者在$group
中对数字属性求和:
1 | { $sum: <expression> } |
在$project
中对数组属性求和:
1 | { $sum: [ <expression>, <expression> ] } |
含义:
名称 | 类型 | 说明 |
---|---|---|
expression | 数字或属性 | 使用$属性 的方式指定属性,忽略非数字的属性值。 |
对文档按sex属性分组,统计文档数量并计算age属性的总和:
1 | db.student.aggregate({ |
统计文档scores数组的总和作为totalScore属性返回,只显示name属性和totalScore属性:
1 | db.student.aggregate({ |
3.2.3 avg
计算并返回数字的平均值。
在$project
中对数组属性求平均值,或者在$group
中对数字属性求平均值:
1 | { $avg: <expression> } |
在$project
中对数组属性求平均值:
1 | { $avg: [ <expression>, <expression> ] } |
含义:
名称 | 类型 | 说明 |
---|---|---|
expression | 数字或属性 | 使用$属性 的方式指定属性,忽略非数字的属性值。 |
对文档按sex属性分组,统计文档数量并计算age属性的平均值:
1 | db.student.aggregate({ |
统计文档scores数组的平均值作为meanScore属性返回,只显示name属性和meanScore属性:
1 | db.student.aggregate({ |
3.2.4 cond
条件表达式,根据条件执行表达式。
根据条件执行表达式:
1 | { |
含义:
名称 | 类型 | 说明 |
---|---|---|
expression | 文档 | 计算结果为布尔类型的表达式。 |
trueCase | 文档 | 计算结果为true时返回此表达式的结果。 |
falseCase | 文档 | 计算结果为false时返回此表达式的结果。 |
统计文档scores数组的总和,根据是否超过250作为level属性,返回name属性和level属性:
1 | db.student.aggregate({ |
条