我收集了不同演员的活动集。现在,我需要计算每个参与者发生的事件数量,即自上次事件发生以来的时间x。
一个更具体的示例:由不同参与者进行的登录事件的集合。自上次登录以来少于8小时发生的每个登录事件均应忽略。因此,假设我在下午2点登录,然后在晚上11点登录,我们想要的计数为2。如果我要在下午2点登录,然后在下午5点登录,则该计数必须为1。
我真的没有看到使用聚合框架解决此问题的可行方法。一种可能的解决方案是为每个记录计算(并保存)上一个事件之间的时间。但是我觉得应该有一个更好的解决方案。
有人能指出我正确的方向吗?并没有真正找到与此用例相似的用例。
如果我的问题不清楚,请告诉我!
修改:
一个例子:
简化事件:
[{
_id: 1,
actor: X,
date: ISODate("2018-09-20T18:00:00.000Z")
},
{
_id: 2,
actor: X,
date: ISODate("2018-09-21T05:00:00.000Z") // 11 hours since previous
},
{
_id: 3,
actor: X,
date: ISODate("2018-09-21T07:00:00.000Z") // 2 hours since previous
},
{
_id: 4,
actor: Y,
date: ISODate("2018-09-21T06:00:00.000Z")
},
{
_id: 5,
actor: Y,
date: ISODate("2018-09-21T09:00:00.000Z") // 3 hours since previous
}]
预期输出:
[{
_id: X,
count: 2 // 3 events, but one is less than 8 hours since previous
},
{
_id: Y,
count: 1 // 2 events, but one is less than 8 hours since previous
}]
答案 0 :(得分:1)
您可以比较不同文档中的值,方法是将它们分组为数组并对其进行迭代。就您而言,$reduce可能是最简单的方法:
db.collection.aggregate([
// ensure order
{ $sort: { date: 1 } },
// get all dates per actor
{ $group: { _id: "$actor", dates: { $push: "$date" } } },
{ $addFields: {
// iterate dates
events: { $reduce: {
input: "$dates",
initialValue: { last: null, count: 1 },
// increment counter if difference is > than 8 * 60 * 60 * 1000 millis
in: { last: "$$this", count: { $add: [
"$$value.count",
{ $cond: [
{$gt: [ { $subtract: [ "$$this", "$$value.last" ] }, 28800000 ] },
1,
0
] }
] } }
} }
} },
{ $project: { count: "$events.count" } }
])
在大型数据集上会变慢。在这种情况下,您可能需要在插入时预先汇总计数器。