diff --git a/server/src/repositories/monitors/IMonitorsRepository.ts b/server/src/repositories/monitors/IMonitorsRepository.ts index 90fcc5a94..dcd01f3c9 100644 --- a/server/src/repositories/monitors/IMonitorsRepository.ts +++ b/server/src/repositories/monitors/IMonitorsRepository.ts @@ -26,6 +26,7 @@ export interface IMonitorsRepository { // collection fetch findAll(): Promise; findByTeamId(teamId: string, config: TeamQueryConfig): Promise; + findByTeamIdWithStats(teamId: string, config: TeamQueryConfig): Promise; findByIds(monitorIds: string[]): Promise; findByIdsWithChecks(monitorIds: string[], checksCount?: number): Promise; diff --git a/server/src/repositories/monitors/MongoMonitorsRepository.ts b/server/src/repositories/monitors/MongoMonitorsRepository.ts index 3d1f9c3a5..07382921a 100644 --- a/server/src/repositories/monitors/MongoMonitorsRepository.ts +++ b/server/src/repositories/monitors/MongoMonitorsRepository.ts @@ -85,6 +85,71 @@ class MongoMonitorsRepository implements IMonitorsRepository { return this.mapDocuments(documents); }; + findByTeamIdWithStats = async (teamId: string, config: TeamQueryConfig): Promise => { + const { page = 0, rowsPerPage = 0, filter, field = "createdAt", order = "desc", type, tags } = config ?? {}; + + const query: Record = { + teamId: new mongoose.Types.ObjectId(teamId), + }; + + if (type !== undefined) { + query.type = Array.isArray(type) ? { $in: type } : type; + } + + if (tags !== undefined) { + query.tags = Array.isArray(tags) ? { $in: tags } : tags; + } + + if (filter !== undefined) { + switch (field) { + case "name": + query.$or = [{ name: { $regex: filter, $options: "i" } }, { url: { $regex: filter, $options: "i" } }]; + break; + case "isActive": + query.isActive = filter === "true"; + break; + case "status": + query.status = filter; + break; + case "type": + query.type = filter; + break; + default: + break; + } + } + + const sort = { [field]: order === "asc" ? 1 : -1 } as const; + const skip = Math.max(page, 0) * rowsPerPage; + + const pipeline: PipelineStage[] = [ + { $match: query }, + { $sort: sort }, + ...(rowsPerPage ? [{ $skip: skip }, { $limit: rowsPerPage }] : []), + { + $lookup: { + from: "monitorstats", + localField: "_id", + foreignField: "monitorId", + as: "stats", + }, + }, + { + $addFields: { + uptimePercentage: { $arrayElemAt: ["$stats.uptimePercentage", 0] }, + }, + }, + { + $project: { + stats: 0, + }, + }, + ]; + + const documents = await MonitorModel.aggregate(pipeline); + return documents.map((doc) => this.toEntity(doc)); + }; + findByIds = async (monitorIds: string[]): Promise => { const objectIds = monitorIds.map((id) => new mongoose.Types.ObjectId(id)); const monitors = await MonitorModel.find({ _id: { $in: objectIds } }); diff --git a/server/src/service/business/monitorService.ts b/server/src/service/business/monitorService.ts index 46b81a2ca..d172107c9 100644 --- a/server/src/service/business/monitorService.ts +++ b/server/src/service/business/monitorService.ts @@ -393,7 +393,7 @@ export class MonitorService implements IMonitorService { }): Promise => { const summary = await this.monitorsRepository.findMonitorsSummaryByTeamId(teamId, { type, tags }); const count = await this.monitorsRepository.findMonitorCountByTeamIdAndType(teamId, { type, tags, filter }); - const monitors = await this.monitorsRepository.findByTeamId(teamId, { + const monitors = await this.monitorsRepository.findByTeamIdWithStats(teamId, { limit, type, tags,