给定的文件如
{
_id: 'abcd',
userId: '12345',
activities: [
{ status: 'login', timestamp: '10000001' },
{ status: 'logout', timestamp: '10000002' },
{ status: 'login', timestamp: '10000003' },
{ status: 'logout', timestamp: '10000004' },
]
}
我正在尝试创建一个管道,例如将返回在两个时间戳之间记录有最新登录/注销活动的所有用户。例如,如果两个时间戳值在10000002
和之间10000003
,则预期文档应为
{
_id: 'abcd',
userId: '12345',
login: '10000003',
logout: '10000002'
}
如果两个时间戳值在-1
和之间10000001
,则预期文档应为:
{
_id: 'abcd',
userId: '12345',
login: '10000001',
logout: null
}
等等。
我知道它与聚合有关,我需要$unwind
等等,但是我不确定其余的事情,即评估同一文档数组中的两个字段
您可以尝试以下汇总:
db.col.aggregate([
{
$unwind: "$activities"
},
{
$match: {
$and: [
{ "activities.timestamp": { $gte: "10000001" } },
{ "activities.timestamp": { $lte: "10000002" } }
]
}
},
{
$sort: {
"activities.timestamp": -1
}
},
{
$group: {
_id: "$_id",
userId: { $first: "$userId" },
activities: { $push: "$activities" }
}
},
{
$addFields: {
login: { $arrayElemAt: [ { $filter: { input: "$activities", as: "a", cond: { $eq: [ "$$a.status", "login" ] } } } , 0 ] },
logout: { $arrayElemAt: [ { $filter: { input: "$activities", as: "a", cond: { $eq: [ "$$a.status", "logout" ] } } } , 0 ] }
}
},
{
$project: {
_id: 1,
userId: 1,
login: { $ifNull: [ "$login.timestamp", null ] },
logout: { $ifNull: [ "$logout.timestamp", null ] }
}
}
])
我们需要使用$ unwind + $ sort + $ group来确保我们的活动将按时间戳进行排序。之后,$unwind
您可以使用$ match来应用过滤条件。然后,可以将$ filter与$ arrayElemAt一起使用以获取过滤后的数组的第一个(最新)值。最后,$project
您可以显式使用$ ifNull(否则,如果没有值,则将跳过JSON键)
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句