Mongoose的 aggregate()
函数 是您如何将 MongoDB 的Aggregation Framework 与 Mongoose 一起使用。 Mongoose的 aggregate()
中工作的任何聚合查询都 MongoDB shell 应该在 Mongoose 中工作,无需任何更改。
什么是 Aggregation Framework ?
从语法上讲,Aggregation Framework 查询是一系列阶段。 阶段 是 MongoDB 如何转换进入阶段的任何文档的对象描述 第一阶段将文档馈送到第二阶段,依此类推,因此您可以使用阶段组合转换。 您传递给的阶段数组 aggregate()
函数称为聚合 管道 。
$match
阶段
$match
阶段过滤掉与给定不匹配的文档 filter
参数,类似于 Mongoose 的 find()
功能 。
await Character.create([
{ name: Jean-Luc Picard, age: 59, rank: Captain },
{ name: William Riker, age: 29, rank: Commander },
{ name: Deanna Troi, age: 28, rank: Lieutenant Commander },
{ name: Geordi La Forge, age: 29, rank: Lieutenant },
{ name: Worf, age: 24, rank: Lieutenant }
]);
const filter = { age: { $gte: 30 } };
let docs = await Character.aggregate([
{ $match: filter }
]);
docs.length; // 1
docs[0].name; // Jean-Luc Picard
docs[0].age // 59
// `$match` is similar to `find()`
docs = await Character.find(filter);
docs.length; // 1
docs[0].name; // Jean-Luc Picard
docs[0].age // 59
$group
阶段
聚合可以做的不仅仅是过滤文档。您还可以使用Aggregation Framework 来转换文档。 例如 $group
舞台表现得像 reduce()
功能 。 例如 $group
stage 让您计算给定的字符数 age
。
let docs = await Character.aggregate([
{
$group: {
// Each `_id` must be unique, so if there are multiple
// documents with the same age, MongoDB will increment `count`.
_id: $age,
count: { $sum: 1 }
}
}
]);
docs.length; // 4
docs.sort((d1, d2) => d1._id - d2._id);
docs[0]; // { _id: 24, count: 1 }
docs[1]; // { _id: 28, count: 1 }
docs[2]; // { _id: 29, count: 2 }
docs[3]; // { _id: 59, count: 1 }
结合多个阶段
聚合管道的优势在于它的可组合性。 例如您可以结合前面的两个示例,仅按以下方式对字符进行分组 age
如果他们的 age
是 < 30
。
let docs = await Character.aggregate([
{ $match: { age: { $lt: 30 } } },
{
$group: {
_id: $age,
count: { $sum: 1 }
}
}
]);
docs.length; // 3
docs.sort((d1, d2) => d1._id - d2._id);
docs[0]; // { _id: 24, count: 1 }
docs[1]; // { _id: 28, count: 1 }
docs[2]; // { _id: 29, count: 2 }
Mongoose Aggregate
Class
Mongoose 的 aggregate()
函数返回一个 Mongoose 的实例 Aggregate
类 。Aggregate
实例是 thenable ,因此您可以将它们与 await
和 承诺链接。
Aggregate
类还支持用于构建聚合管道的链接接口。 例如,下面的代码显示了构建聚合管道的另一种语法 $match
其次是 $group
。
let docs = await Character.aggregate().
match({ age: { $lt: 30 } }).
group({ _id: $age, count: { $sum: 1 } });
docs.length; // 3
docs.sort((d1, d2) => d1._id - d2._id);
docs[0]; // { _id: 24, count: 1 }
docs[1]; // { _id: 28, count: 1 }
docs[2]; // { _id: 29, count: 2 }
Mongoose 中间件 也支持 pre(aggregate)
和 post(aggregate)
钩子。 您可以使用聚合中间件来转换聚合管道。
const characterSchema = Schema({ name: String, age: Number });
characterSchema.pre(aggregate, function() {
// Add a `$match` to the beginning of the pipeline
this.pipeline().unshift({ $match: { age: { $lt: 30 } } });
});
const Character = mongoose.model(Character, characterSchema);
// The `pre(aggregate)` adds a `$match` to the pipeline.
let docs = await Character.aggregate().
group({ _id: $age, count: { $sum: 1 } });
docs.length; // 3
docs.sort((d1, d2) => d1._id - d2._id);
docs[0]; // { _id: 24, count: 1 }
docs[1]; // { _id: 28, count: 1 }
docs[2]; // { _id: 29, count: 2 }
请登录后查看评论内容