如何通过MongoDB查询计算指定时间范围内系统运行时长?
MongoDB计算指定时间范围内系统开机总时长
假设你的集合名为system_events,给定的起止时间戳为start_ts(起始)和end_ts(结束),可以通过MongoDB聚合管道实现计算,具体操作如下:
核心逻辑
先筛选出目标时间范围内的所有开关机记录,按时间排序后将每条开机(power:on)记录与对应的下一条关机(power:off)记录配对,计算每段开机时长后求和;同时处理边界情况(比如时间范围开始前已开机、结束时仍未关机)。
具体聚合查询代码
db.system_events.aggregate([ // 1. 过滤出eventcode为100、时间在指定范围内的开关机记录 { $match: { "metadata.eventcode": 100, time: { $gte: start_ts, $lte: end_ts }, power: { $in: ["on", "off"] } } }, // 2. 按时间戳升序排列,保证记录顺序符合实际操作流程 { $sort: { time: 1 } }, // 3. 获取每条记录的下一条记录的时间和电源状态 { $setWindowFields: { sortBy: { time: 1 }, output: { next_time: { $lead: "$time" }, next_power: { $lead: "$power" } } } }, // 4. 只保留开机记录,后续针对每段开机时长计算 { $match: { power: "on" } }, // 5. 计算单段开机时长,处理边界情况 { $addFields: { duration: { $cond: [ // 下一条是关机记录时,用关机时间减开机时间 { $and: [{ $ne: ["$next_power", null] }, { $eq: ["$next_power", "off"] }] }, { $subtract: ["$next_time", "$time"] }, // 下一条不存在或仍是开机状态时,用结束时间减开机时间 { $subtract: [end_ts, "$time"] } ] }, // 容错处理:确保时长不为负数 duration: { $max: ["$duration", 0] } } }, // 6. 求和所有开机时长 { $group: { _id: null, total_on_duration: { $sum: "$duration" } } }, // 7. 格式化输出,只保留总时长字段 { $project: { _id: 0, total_on_duration: 1 } } ])
特殊边界补充处理
如果时间范围开始前系统已经开机(即范围内第一条记录是power:off),需要补充一段从start_ts到第一条关机时间的时长。可以在$sort步骤后添加如下逻辑:
{ $addFields: { is_first: { $eq: [{ $indexOfArray: ["$$ROOT.time", "$time"] }, 0] } } }, { $facet: { main: [{ $match: { is_first: { $ne: true } } }], first_check: [{ $match: { is_first: true, power: "off" } }] } }, { $project: { combined: { $concatArrays: [ { $cond: [ { $ne: ["$first_check", []] }, [{ time: start_ts, power: "on" }], [] ] }, "$main" ] } } }, { $unwind: "$combined" }, { $replaceRoot: { newRoot: "$combined" } }
内容的提问来源于stack exchange,提问作者Harsh
相关产品推荐
相关产品推荐

