mongodb - MongoDB每天为每个用户显示第一个和最后一个事件
问题描述
每次用户登录或注销时,都会在 mongo 中保存一个事件。用户可以每天多次登录和/或注销。
例如,Bob 登录 2 次,注销 1 次:
{
username: ‘bob’,
type: ‘login’,
eventDate: ISODate(‘2018-09-21T12:39:50.676Z’)
}
{
username: ‘bob’,
type: ‘login’,
eventDate: ISODate(‘2018-09-21T13:55:50.676Z’)
}
{
username: ‘bob’,
type: ‘logout,
eventDate: ISODate(‘2018-09-21T22:10:50.676Z’)
}
詹姆斯只有 1 个登录事件:
{
username: ‘james’,
type: ‘login,
eventDate: ISODate(‘2018-09-21T10:10:50.676Z’)
}
我想执行一个查询,该查询将检索每个用户每天的第一次登录和当天的最后一次注销(假设在过去一周)。
所以结果会是这样的:
[{
username: ‘bob’,
firstLogin: ISODate(‘2018-09-21T12:39:50.676Z’),
lastLogout: ISODate(‘2018-09-21T22:10:50.676Z’)
}
{
username: ‘james’,
firstLogin: ISODate(‘2018-09-22T10:19:50.676Z’),
lastLogout: null,
}]
我相信我必须处理“聚合”,但不确定。
解决方案
通过使用两个级别$group
:(MongoDB V3.2.18)
我相信userName是独一无二的。
$sort
首先是事件日期。$group
按用户名和类型。$project
区分firstLogin和lastLogin。$group
再次由用户名获得最终结果。
db.getCollection('test').aggregate([
{$sort: {'eventDate' : 1}},
{
"$group" : {
_id: {"username" : "$username", "type": "$type"},
eventDate: {$push: "$eventDate"}
}
},
{
$project : {
_id:1,
eventDate:1,
firstLogin: {
$cond: [ { "$eq": ["$_id.type", "login" ]}, { $arrayElemAt: [ "$eventDate", 0 ] }, null]
},
lastLogout: {
$cond: [ { "$eq": ["$_id.type", "logout" ]}, { $arrayElemAt: [ "$eventDate", -1 ] }, null]
}
}
},
{
"$group" : {
_id: "$_id.username",
firstLogin: {$first: "$firstLogin"},
lastLogout: {$last: "$lastLogout"}
}
}
]);
输出:
/* 1 */
{
"_id" : "james",
"firstLogin" : ISODate("2018-09-21T10:10:50.676Z"),
"lastLogout" : null
}
/* 2 */
{
"_id" : "bob",
"firstLogin" : ISODate("2018-09-21T12:39:50.676Z"),
"lastLogout" : ISODate("2018-09-21T22:10:50.676Z")
}
推荐阅读
- python - 根据滚动时间窗口分配组号 - Pandas
- powershell - Powershell Sharepoint Online - 将内容类型添加到列表
- javascript - 检查文件是否存在,否则加载另一个页面
- javascript - 如何在反应中将数据从一个组件传输到另一个组件?
- javascript - 计算日期之间的差异并从该结果开始计时器计数
- javascript - 在元素上调用事件
- javascript - Await 仅在带有 nodejs 的异步函数中有效
- spring-boot - 两次读取 apache HttpClient 响应
- docker - 在 Linux 环境下,ec2 上的 docker 无法连接到 X 服务器问题
- go - GRPC-GO:生成的 pb.go 文件中未显示客户端存根