jiknjikn 2024-10-25 13:40 采纳率: 0%
浏览 4
已结题

mongodb 上下文档聚合计算时长

有一集合collection文档是:

// 1
{
    "_id": ObjectId("671373c040d1040b60314ca5"),
    "machine_code": "WB01",
    "alarmid": "11",
    "isset": true,
    "alarmtxt": "测试",
    "alarm_type": "5",
    "c_datetime": ISODate("2024-10-19T16:54:24.3Z")
}

// 2
{
    "_id": ObjectId("671373c040d1040b60314ca6"),
    "machine_code": "WB01",
    "alarmid": "11",
    "isset": false,
    "alarmtxt": "测试",
    "alarm_type": "5",
    "c_datetime": ISODate("2024-10-19T16:54:24.788Z")
}

// 3
{
    "_id": ObjectId("671373c140d1040b60314ca7"),
    "machine_code": "WB01",
    "alarmid": "11",
    "isset": true,
    "alarmtxt": "测试",
    "alarm_type": "5",
    "c_datetime": ISODate("2024-10-19T16:54:25.394Z")
}

// 4
{
    "_id": ObjectId("671373c140d1040b60314ca8"),
    "machine_code": "WB01",
    "alarmid": "11",
    "isset": false,
    "alarmtxt": "测试",
    "alarm_type": "5",
    "c_datetime": ISODate("2024-10-19T16:54:25.939Z")
}

同一machine_code,alarmid下,isset 一真一假,时间相近的视为一对,求取时间间隔
问题:如何写mongodb的聚合管道 或者 视图创建 来获取时长?

  • 写回答

2条回答 默认 最新

  • zhengmingren 2024-10-25 14:46
    关注

    在MongoDB中,你可以使用聚合管道(Aggregation Pipeline)来处理这种类型的数据。聚合管道允许你处理和组合数据,以生成复杂的输出。对于你的需求,我们可以按照以下步骤来设计聚合管道:

    1. 分组(Group):首先,我们需要根据machine_codealarmid来分组,同时记录下每组中issettruefalse的文档。
    2. 排序(Sort):在分组后,我们需要对每个分组内的文档按照时间c_datetime进行排序。
    3. 匹配(Match):然后,我们可以匹配出每个分组中issettruefalse的文档。
    4. 投影(Project):最后,我们需要计算时间差,并将其作为输出。

    以下是一个可能的聚合管道示例:

    db.collection.aggregate([
        {
            $sort: {
                "machine_code": 1,
                "alarmid": 1,
                "c_datetime": 1
            }
        },
        {
            $group: {
                _id: {
                    machine_code: "$machine_code",
                    alarmid: "$alarmid"
                },
                trueSet: { $first: { $ifNull: ["$isset", false] } },
                falseSet: { $last: { $ifNull: ["$isset", true] } },
                trueTime: { $first: "$c_datetime" },
                falseTime: { $last: "$c_datetime" }
            }
        },
        {
            $project: {
                _id: 0,
                machine_code: "$_id.machine_code",
                alarmid: "$_id.alarmid",
                duration: {
                    $cond: {
                        if: { $and: ["$trueSet", "$falseSet"] },
                        then: { $subtract: ["$falseTime", "$trueTime"] },
                        else: null
                    }
                }
            }
        },
        {
            $addFields: {
                duration: {
                    $toLong: { $multiply: [{ $dayOfMonth: "$duration" }, 24*60*60*1000] }
                }
            }
        }
    ])
    

    这个聚合管道做了以下几件事情:

    • 首先,它对文档按照machine_codealarmidc_datetime进行排序。
    • 然后,它根据machine_codealarmid对文档进行分组,并使用$first$last来获取每个分组中issettruefalse的文档的时间戳。
    • 接着,它使用$project来计算时间差,并将其作为duration字段输出。
    • 最后,它使用$addFields来将时间差转换为毫秒。

    请注意,这个示例假设isset字段要么是true要么是false,并且每个分组中恰好有一个true和一个false。如果实际情况有所不同,你可能需要调整这个聚合管道以适应你的具体需求。此外,这个示例没有考虑时区和夏令时的影响,如果需要,你可能需要进一步处理时间戳。

    评论

报告相同问题?

问题事件

  • 已结题 (查看结题原因) 10月28日
  • 创建了问题 10月25日