前言
MongoDB中,聚合框架是一种高级查询语言,我们可以通过转换和合并多个文档中的数据来生成新的单个文档中不存在的信息。
aggregate() 方法
聚合框架的所有操作都是基于aggregate方法。该方法接受一个参数,这个参数是一个数组,其中可以包含一个或者多个聚合操作。常见的聚合操作如下:
命令 | 功能 |
---|---|
$project | 指定输出文档里的字段. |
$match | 选择要处理的文档 |
$limit | 限制传递给下一步的文档数量。 |
$skip | 跳过一定数量的文档。 |
$unwind | 扩展数组,为每个数组入口生成一个输出文档。 |
$group | 根据key来分组文档。 |
$sort | 排序文档。 |
$geoNear | 选择某个地理位置附近的的文档。 |
$out | 把管道的结果写入某个集合。 |
$redact | 控制特定数据的访问。 |
$lookup | 多表关联 |
举个例子,这里使用了$group以原文档的name作为主键创建了一个新的文档。
> db.studentInfo.find()
{ "_id" : ObjectId("61234d6713e48bd44324e7fe"), "name" : "mark", "age" : 20 }
{ "_id" : ObjectId("61234d6713e48bd44324e7ff"), "name" : "Tom", "age" : 25 }
> db.studentInfo.aggregate([{$group: {_id: "$name"}}])
{ "_id" : "Tom" }
{ "_id" : "mark" }
我再插入了一条数据,试试传多个聚合操作
> db.studentInfo.find()
{ "_id" : ObjectId("61234d6713e48bd44324e7fe"), "name" : "mark", "age" : 20 }
{ "_id" : ObjectId("61234d6713e48bd44324e7ff"), "name" : "Tom", "age" : 25 }
{ "_id" : ObjectId("612373633d21fba9cc88fcee"), "name" : "yellowbird", "age" : 23 }
> db.studentInfo.aggregate([{$match: {age: {$gt: 20}}}, {$group: {_id: null, count:{$sum : 1}}}])
{ "_id" : null, "count" : 2 }
>
这里是用match操作匹配了大于20岁的数据,并用group输出了统计超过20岁的人数总和的新文档。
联表查询$lookup
为了便于理解,我直接上实例,从实例中了解语法。以上面那个学生信息表(studentInfo)为基础,这里我再创建了一个成绩表(scoreList),并插入了一组成绩单的数据如下:
> db.scoreList.find()
{ "_id" : ObjectId("6123c74d3d21fba9cc88fcef"), "name" : "Tom", "score" : 95 }
{ "_id" : ObjectId("6123c75e3d21fba9cc88fcf0"), "name" : "mark", "score" : 57 }
{ "_id" : ObjectId("6123c76a3d21fba9cc88fcf1"), "name" : "yellowbird", "score" : 77 }
然后将学生的成绩和个人信息进行一个联表查询,以学生的name作为
> db.scoreList.aggregate([{ $lookup:{ from: "studentInfo", localField: "name", foreignField: "name", as: "newInfo" }}])
{
"_id" : ObjectId("6123c74d3d21fba9cc88fcef"),
"name" : "Tom",
"score" : 95,
"newInfo" : [{
"_id" : ObjectId("61234d6713e48bd44324e7ff"),
"name" : "Tom",
"age" : 25
}]
}
{
"_id" : ObjectId("6123c75e3d21fba9cc88fcf0"),
"name" : "mark",
"score" : 57,
"newInfo" : [{
"_id" : ObjectId("61234d6713e48bd44324e7fe"),
"name" : "mark",
"age" : 20
}]
}
{
"_id" : ObjectId("6123c76a3d21fba9cc88fcf1"),
"name" : "yellowbird",
"score" : 77,
"newInfo" : [{
"_id" : ObjectId("612373633d21fba9cc88fcee"),
"name" : "yellowbird",
"age" : 23
} ]
}
注意,在没有其他聚合操作的情况下,$lookup的输出文档的长度是与输入文档的长度是一致的。另外由于文档的结构相对比较自由,如果两个集合均不存在比较的key值,则同样会匹配输出文档,因为null == null。