MongoDB aggregation
The MongoDB database contains a mechanism called the MongoDB aggregation framework. It is working with the concepts of data processing pipelines. Documents enter a multi-stage pipeline that can transform them and output the aggregated result.
Since there might be multiple stages, we pass an array to the aggregate function. Every element of that array is an object that has a property naming one of the possible stages that you can use. For example:
const arrayOfJohns = await this.user.aggregate(
[
{
$match: {
name: 'John',
},
},
],
);
Using $match works similarly to the find function.
The output of a stage is later passed to the next stage in the array if there are any.
$group
// src/controller/report/report.controller.ts
import express from 'express';
import Controller from '../../interfaces/controller.interface';
import userModel from '../../models/users/user.model';
class ReportController implements Controller {
public path = '/report';
public router = express.Router();
private user = userModel;
constructor() {
this.initializeRoutes();
}
private initializeRoutes() {
this.router.get(`${this.path}`, this.generateReport);
}
private generateReport = async (request: express.Request, response: express.Response, next: express.NextFunction) => {
const usersByCountries = await this.user.aggregate(
[
{
$group: {
_id: {
country: '$address.country',
},
},
},
]
);
response.send({
usersByCountries
});
}
}
export default ReportController;
``
```ts
// src/server.ts
const app = new App(
[
new PostsController(),
new AuthenticationController(),
new ReportController(),
],
);
app.listen();
Combining multiple stages
//src/controller/report/report.controller.ts
import express from "express";
import Controller from "../../interfaces/controller.interface";
import userModel from "../../models/users/user.model";
class ReportController implements Controller {
public path = "/report";
public router = express.Router();
private userModel = userModel;
constructor() {
this.initializeRoutes();
}
private initializeRoutes() {
this.router.get(`${this.path}`, this.generateReport);
}
private generateReport = async (
request: express.Request,
response: express.Response,
next: express.NextFunction
) => {
const usersByCountries = await this.userModel.aggregate([
{
$match: {
"address.country": {
$exists: true,
},
},
},
{
$group: {
_id: {
country: "$address.country",
},
count: {
$sum: 1,
},
users: {
$push: {
name: "$firstName",
_id: "$_id",
},
},
},
},
]);
response.send({
usersByCountries,
});
};
}
export default ReportController;
$lookup
ref: source