mongodb - 从 MongoDB 中的同一数组返回包含两个字段的文档

标签 mongodb mongodb-query aggregation-framework

给定文件如

{
  _id: 'abcd',
  userId: '12345',
  activities: [
    { status: 'login', timestamp: '10000001' },
    { status: 'logout', timestamp: '10000002' },
    { status: 'login', timestamp: '10000003' },
    { status: 'logout', timestamp: '10000004' },
  ]
}

我正在尝试创建一个管道,例如所有在两个时间戳之间记录了最新登录/注销事件的用户都将被返回。例如,如果两个时间戳值介于 1000000210000003 之间,则预期的文档应该是

{
  _id: 'abcd',
  userId: '12345',
  login: '10000003',
  logout: '10000002'
}

如果两个时间戳值介于-110000001 之间,则预期的文档应该是:

{
  _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 键)

关于mongodb - 从 MongoDB 中的同一数组返回包含两个字段的文档,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53415876/

相关文章:

mongodb - MongoDB 的待办事项列表模式设计有什么建议?

mongodb - 如何在 Mongo 聚合中合并文档中的数组字段

javascript - 更新使用 Mongoose 模型检索并作为 promise 处理的文档时出现问题

mongodb - 如何使 mongodb 使用 countDocuments() 和 $addFields

node.js - Mongoose 用户通过电话号码批量搜索

Redis 上的 "subscribe"中的 MongoDB

mongodb - 使用 shell 中的奇怪字符访问 MONGO 集合,第二部分

mongodb - MongoDB 中的反向数组字段

performance - mongo高效地从大集合中删除数据

java - 从文档中获取多个整数,将它们组合起来,除以值并从集合中获取顶部结果