代码之家  ›  专栏  ›  技术社区  ›  dalf

MongoBD显示每个用户每天的第一个和最后一个事件

  •  0
  • dalf  · 技术社区  · 7 年前

    每次用户登录或注销时,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’)
    }
    

    James只有一个登录事件:

    {
      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,
    }]
    

    我相信我必须处理聚合,但不确定。

    2 回复  |  直到 7 年前
        1
  •  1
  •   Community Mohan Dere    6 年前

    group .

    当同一个用户有不同的工作日时也可以使用。

    type .

    db.getCollection("loginDetail").aggregate([
      {
        $group: {
          _id: {
            username: "$username",
            year: { $year: "$eventDate" },
            month: { $month: "$eventDate" },
            day: { $dayOfMonth: "$eventDate" }
          },
          firstLogin: {
            $min: {
              $cond: [{ $and: [{ $eq: ["$type", "login"] }] }, "$eventDate", null]
            }
          },
          lastLogout: {
            $max: {
              $cond: [{ $and: [{ $eq: ["$type", "logout"] }] }, "$eventDate", null]
            }
          }
        }
      },
      {
          $project: {
              _id: 1,
              username : '$_id.username',
              firstLogin :1,
              lastLogout :1
              }
          }
    ]);
    
        2
  •  2
  •   Hardik Shah    7 年前

    通过使用两个级别的 $group (MongoDB 3.2.18版)

    我相信 是独一无二的。

    1. $sort 第一。
    2. 通过 用户名 类型 .
    3. $project 区分 首次登录 上次登录
    4. $组 再一次 用户名 最终结果。

    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")
    }
    
    推荐文章