MongoDB Aggregate如何配对相关记录进行处理

标签 mongodb aggregate

我在 MongoDB 数据库中捕获了一些事件数据,其中一些事件成对发生。

例如:DOOR_OPEN 和 DOOR_CLOSE 是成对发生的两个事件

事件集合:

{ _id: 1, name: "DOOR_OPEN", userID: "user1", timestamp: t }
{ _id: 2, name: "DOOR_OPEN", userID: "user2", timestamp: t+5 }
{ _id: 3, name: "DOOR_CLOSE", userID: "user1", timestamp:t+10 }
{ _id: 4, name: "DOOR_OPEN", userID: "user1", timestamp:t+30 }
{ _id: 5, name: "SOME_OTHER_EVENT", userID: "user3", timestamp:t+35 }
{ _id: 6, name: "DOOR_CLOSE", userID: "user2", timestamp:t+40 }
...

假设记录按时间戳排序,则“user1”的 _id: 1 和 _id: 3 是一对。“user2”的 _id: 2 和 _id: 6 是一对。

我想获取每个用户的所有这些 DOOR_OPEN 和 DOOR_CLOSE 对,并计算平均持续时间等。门已被每个用户打开。

这可以使用聚合框架来实现吗?

最佳答案

您可以使用 $lookup 和 $group 来实现此目的。

db.getCollection('TestColl').aggregate([
{ $match: {"name": { $in: [ "DOOR_OPEN", "DOOR_CLOSE" ] } }},
{ $lookup:
       {
         from: "TestColl",
         let: { userID_lu: "$userID", name_lu: "$name", timestamp_lu :"$timestamp" },
         pipeline: [
              { $match:
                 { $expr:
                    { $and:
                       [
                         { $eq: [ "$userID",  "$$userID_lu" ] },
                         { $eq: [ "$$name_lu", "DOOR_OPEN" ]},
                         { $eq: [ "$name", "DOOR_CLOSE" ]},
                         { $gt: [ "$timestamp", "$$timestamp_lu" ] }
                       ]
                    }
                 }
              },              
           ],
         as: "close_dates"
       }
},
{ $addFields: { "close_time": { $arrayElemAt: [ "$close_dates.timestamp", 0 ] }  } },
{ $addFields: { "time_diff": { $divide: [ { $subtract: [ "$close_time", "$timestamp" ] }, 1000 * 60 ]} } }, // Minutes
{ $group: { _id: "$userID" , 
    events: { $push: { "eventId": "$_id", "name": "$name",  "timestamp": "$timestamp" } },
    averageTimestamp: {$avg: "$time_diff"}
    }
}
])

示例数据:

[
{ _id: 1, name: "DOOR_OPEN", userID: "user1", timestamp: ISODate("2019-10-24T08:00:00Z") },
{ _id: 2, name: "DOOR_OPEN", userID: "user2", timestamp: ISODate("2019-10-24T08:05:00Z") },
{ _id: 3, name: "DOOR_CLOSE", userID: "user1", timestamp:ISODate("2019-10-24T08:10:00Z") },
{ _id: 4, name: "DOOR_OPEN", userID: "user1", timestamp:ISODate("2019-10-24T08:30:00Z") },
{ _id: 5, name: "SOME_OTHER_EVENT", userID: "user3", timestamp:ISODate("2019-10-24T08:35:00Z") },
{ _id: 6, name: "DOOR_CLOSE", userID: "user2", timestamp:ISODate("2019-10-24T08:40:00Z") },
{ _id: 7, name: "DOOR_CLOSE", userID: "user1", timestamp:ISODate("2019-10-24T08:50:00Z") },
{ _id: 8, name: "DOOR_OPEN", userID: "user2", timestamp:ISODate("2019-10-24T08:55:00Z") }
]

结果:

/* 1 */
{
    "_id" : "user2",
    "events" : [ 
        {
            "eventId" : 2.0,
            "name" : "DOOR_OPEN",
            "timestamp" : ISODate("2019-10-24T08:05:00.000Z")
        }, 
        {
            "eventId" : 6.0,
            "name" : "DOOR_CLOSE",
            "timestamp" : ISODate("2019-10-24T08:40:00.000Z")
        }, 
        {
            "eventId" : 8.0,
            "name" : "DOOR_OPEN",
            "timestamp" : ISODate("2019-10-24T08:55:00.000Z")
        }
    ],
    "averageTimestamp" : 35.0
}

/* 2 */
{
    "_id" : "user1",
    "events" : [ 
        {
            "eventId" : 1.0,
            "name" : "DOOR_OPEN",
            "timestamp" : ISODate("2019-10-24T08:00:00.000Z")
        }, 
        {
            "eventId" : 3.0,
            "name" : "DOOR_CLOSE",
            "timestamp" : ISODate("2019-10-24T08:10:00.000Z")
        }, 
        {
            "eventId" : 4.0,
            "name" : "DOOR_OPEN",
            "timestamp" : ISODate("2019-10-24T08:30:00.000Z")
        }, 
        {
            "eventId" : 7.0,
            "name" : "DOOR_CLOSE",
            "timestamp" : ISODate("2019-10-24T08:50:00.000Z")
        }
    ],
    "averageTimestamp" : 15.0
}

关于MongoDB Aggregate如何配对相关记录进行处理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58535108/

相关文章:

MongoDB:删除多个对象内的项目

mongodb - 如何在mongodb中查找子数组?

r - 按缺失数据值的组聚合数据

mysql - 按周分组的记录数的累计总和

json - MongoDB 在具有未知键的集合中查找

c# - 在 MongoDB 中存储动态 JSON 数据

mongodb - 从mongodb docker-container运行脚本

mongodb java插入嵌入式文档

r - 如何在R中聚合分类数据?

r - 在 R 中计数并保留出现的顺序