MongoDB如何关联两个集合并从第二个集合取单条数据计算节点宕机时长
MongoDB 3.4 实现节点DOWN状态时长计算方案
以下方案完全兼容MongoDB 3.4.24版本特性,通过聚合查询即可实现需求:
实现逻辑
- 从
health集合筛选目标节点的当前DOWN状态记录 - 关联
health_history集合拉取该节点所有历史健康记录 - 过滤出历史中状态为UP的记录,按创建时间倒序取最新的一条
- 计算当前DOWN记录的创建时间和最新UP记录创建时间的分钟差,作为
duration字段输出
完整查询代码
db.health.aggregate([ // 筛选Test节点的当前DOWN状态记录,如需查询所有DOWN节点可删除name匹配条件 { $match: { name: "Test", status: "DOWN" } }, // 关联该节点的所有历史健康记录 { $lookup: { from: "health_history", localField: "name", foreignField: "name", as: "history_records" } }, // 展开历史记录数组 { $unwind: "$history_records" }, // 过滤仅保留UP状态的历史记录 { $match: { "history_records.status": "UP" } }, // 按历史记录创建时间倒序,最新的UP记录排在最前 { $sort: { "history_records.create_time": -1 } }, // 分组保留原始健康记录字段,同时取最新的UP记录时间 { $group: { _id: "$_id", name: { $first: "$name" }, snapshot_time: { $first: "$snapshot_time" }, status: { $first: "$status" }, create_time: { $first: "$create_time" }, latest_up_time: { $first: "$history_records.create_time" } } }, // 计算分钟差,得到时长字段duration { $addFields: { duration: { // 毫秒转分钟后向下取整,如需向上取整可替换为$ceil $floor: { $divide: [ { $subtract: [ "$create_time", "$latest_up_time" ] }, 60000 ] } } } }, // 移除不需要的中间字段 { $project: { latest_up_time: 0 } } ])
异常场景兼容
如果目标节点没有历史UP状态记录,上述查询会返回空结果。如需兼容该场景,可以在$group步骤后新增$addFields步骤,通过$ifNull给latest_up_time设置默认值(比如节点首次接入时间、当前时间等)即可。
内容的提问来源于stack exchange,提问作者developthou
相关产品推荐
相关产品推荐

