add uptimetime stats method and aggregation

This commit is contained in:
Alex committed 2026-06-06 16:08:00 -07:00
1 parent 73b74ffd80
commit 395b7fbe2a
3 files changed
+67 -1

No files matched your search

@@ -26,6 +26,7 @@ export interface IMonitorsRepository {
// collection fetch
findAll(): Promise<Monitor[] | null>;
findByTeamId(teamId: string, config: TeamQueryConfig): Promise<Monitor[] | null>;
findByTeamIdWithStats(teamId: string, config: TeamQueryConfig): Promise<Monitor[] | null>;
findByIds(monitorIds: string[]): Promise<Monitor[]>;
findByIdsWithChecks(monitorIds: string[], checksCount?: number): Promise<Monitor[]>;
@@ -85,6 +85,71 @@ class MongoMonitorsRepository implements IMonitorsRepository {
return this.mapDocuments(documents);
};
findByTeamIdWithStats = async (teamId: string, config: TeamQueryConfig): Promise<Monitor[] | null> => {
const { page = 0, rowsPerPage = 0, filter, field = "createdAt", order = "desc", type, tags } = config ?? {};
const query: Record<string, unknown> = {
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<Monitor[]> => {
const objectIds = monitorIds.map((id) => new mongoose.Types.ObjectId(id));
const monitors = await MonitorModel.find({ _id: { $in: objectIds } });
@@ -393,7 +393,7 @@ export class MonitorService implements IMonitorService {
}): Promise<MonitorsWithChecksByTeamIdResult> => {
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,