对聚合日期字段 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 秒。
所以,我正在使用 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 秒。