对聚合日期字段 MongoDB 进行移位 windows 操作

Shifting windows operation on aggregate date field MongoDB

所以,我正在使用 mongodb 3.6.0 驱动程序

我在 运行 这个命令之后有一个结果集合:

db.commands.aggregate([{$project: { _id:0 ,user: 1, purchaseDate: 1}},{$sort: {user: 1, purchaseDate: 1}}],{allowDiskUse: true})

看起来像这样:

{ "user" : "1", "purchaseDate" : ISODate("2015-03-09T00:18:38") }
{ "user" : "1", "purchaseDate" : ISODate("2015-03-09T09:44:09") }
{ "user" : "1", "purchaseDate" : ISODate("2015-03-09T09:44:11") }
{ "user" : "2", "purchaseDate" : ISODate("2015-03-09T09:15:57") }
{ "user" : "2", "purchaseDate" : ISODate("2015-03-09T11:32:22") }
{ "user" : "3", "purchaseDate" : ISODate("2015-03-09T13:40:15") }
{ "user" : "4", "purchaseDate" : ISODate("2015-03-09T04:18:57") }
{ "user" : "5", "purchaseDate" : ISODate("2015-03-09T14:46:52") }
{ "user" : "6", "purchaseDate" : ISODate("2015-03-09T16:51:19") }
{ "user" : "7", "purchaseDate" : ISODate("2015-03-09T09:37:53") }
{ "user" : "8", "purchaseDate" : ISODate("2015-03-09T16:25:25") }
{ "user" : "8", "purchaseDate" : ISODate("2015-03-09T16:26:20") }
{ "user" : "8", "purchaseDate" : ISODate("2015-03-09T17:12:57") }

我想计算同一用户两次购买之间经过的时间(秒或分钟)。使每个文档看起来像这样:

{ "user" : "1", "purchaseDate" : ISODate("2015-03-09T00:18:38"), "delta_seconds": 0 }
{ "user" : "1", "purchaseDate" : ISODate("2015-03-09T09:44:09"), "delta_seconds": 33931 }
{ "user" : "1", "purchaseDate" : ISODate("2015-03-09T09:44:11"), "delta_seconds": 2 }
{ "user" : "2", "purchaseDate" : ISODate("2015-03-09T09:15:57"), "delta_seconds": 0 }
{ "user" : "2", "purchaseDate" : ISODate("2015-03-09T11:32:22"), "delta_seconds":  6491}

...
and so on.

谁能帮帮我?

您可以尝试以下聚合:

db.purchases.aggregate([
    { 
        $sort: { purchaseDate: 1 } 
    },
    {
        $group: {
            _id: "$user",
            purchaseDate: { $push: "$purchaseDate" },
            propertyToUnwind: { $push: 1 }
        }
    },
    {
        $unwind: {
            path: "$propertyToUnwind",
            includeArrayIndex: "index"
        }
    },
    {
        $project: {
            user: "$_id",
            delta_miliseconds: { 
                $cond: { if: { $eq: [ "$index", 0 ] }, 
                    then: 0, 
                    else: { 
                        $subtract: [
                            { $arrayElemAt: [ "$purchaseDate", "$index" ] }, 
                            { $arrayElemAt: [ "$purchaseDate", { $subtract: [ "$index", 1 ] } ] }
                        ] 
                    } 
                }
           }
        }
    },
    {
        $project: {
            user: 1,
            delta_seconds: { $divide: [ "$delta_miliseconds", 1000 ] }
        }
    },
    {
        $sort: {
            user: 1
        }
    }
])

基本上,要在聚合框架中获取其他文档的上下文,您需要将它们分组到一个数组中。因此,在第二阶段之后,我们最终得到了每个用户所有日期的数组。我们还添加了人工数组 propertyToUnwind,因为我想利用 $unwind 提供数组索引(includeArrayIndex 选项)这一事实。

有了这个索引,我们可以很容易地减去两个日期(从当前索引和前一个索引)。如果当前处理的文档的索引等于零,我们可以 return 零,因为没有前一个(这就是为什么使用 $cond here). $subtract 日期 returns 毫秒数的原因,所以我们需要将此字段除以1000 秒。