【问题标题】:MongoDB aggregate/group -> get amount of single active users by dateMongoDB 聚合/组 -> 按日期获取单个活跃用户的数量
【发布时间】:2021-04-12 17:32:15
【问题描述】:

我正在尝试汇总保存的用户会话并获取某个日期范围内每个日期的单个活跃访问者的数量。

我有一个包含以下属性的会话模型:

{
  'environment' : ObjectId("xxxxxxxxxxxxxxxxxxxxxxxx"),
  'created'     : ISODate("2021-01-05T22:02:25.757Z"),
  'visitor'     : ObjectId("xxxxxxxxxxxxxxxxxxxxxxxx")
}

结果应该是这样的:

[
  {
    'date'  : '2021-01-03',
    'count' : 5 // this is the amount of unique visitors. If there are two documents with the same date and visitor id, only one should be count.
  },
  {
    'date'  : '2021-01-05',
    'count' : 15 
  },
  {
    'date'  : '2021-01-06',
    'count' : 11
  },
  ...etc...
]

这是我尝试的最后一个管道,当然这是错误的:

const data = await Session.aggregate([
  {
    '$match': {
       environment : ObjectID( args.environment ),
       created     : { '$gte': new Date( args.start ), '$lte': new Date( args.end ) }
    }
  },
  {
    $addFields:{
      createdDate:{
        $dateFromParts:{
          year:{
            $year:"$created"
          }, 
          month:{
            $month:"$created"
          }, 
          day:{
            $dayOfMonth : "$created" 
          }
        }
      }
    }
  },
  {
    $group:{
      _id:{
        date:"$createdDate",visitor:"$visitor"
      },
      count:{$sum:1}
    }
  },
  {
    $project:{
      _id:0,
      date:"$_id.date",
      count:"$count",
    }
  }
])

我为我的管道尝试了一些我自己的组合和一些 SO 组合,但还没有取得很大的成功。

非常感谢您的帮助。

【问题讨论】:

标签: javascript node.js mongodb mongoose aggregation-framework


【解决方案1】:

我认为您正在搜索的是 $addToSet 运算符。

返回一个由所有唯一值组成的数组,该数组是通过对一组文档中的每个文档应用一个表达式而产生的,这些文档按键共享同一组。

文档:https://docs.mongodb.com/manual/reference/operator/aggregation/addToSet/

您只需要按天分组并将访问者 ID 添加到集合中,如果存在则不添加,如果不存在则不添加,然后 kaboom。之后,您只需要计算该列表中有多少元素。

const data = await Session.aggregate([
  {
    $match: {
      environment : ObjectID( args.environment ),
      created     : { '$gte': new Date( args.start ), '$lte': new Date( args.end ) }
    }
  },
  {
    $group: {
      _id: {
        $dateToString: {
          format : "%Y-%m-%d",
          date   : "$created"
        },
      },
      visitors: { $addToSet: "$visitor" }
    }
  },
  {
    $project: {
      _id: 0,
      date: "$_id",
      count: { $size: "$visitors" }
    }
  }
])

【讨论】:

  • 而且 kaboom 有效。差不多吧。但它暗示了我正确的方向。请参阅此小提琴以了解我的最终管道。如果你愿意,你可以用它更新你的答案,我会接受它。因此,人们将来有一个工作片段来查看。非常感谢,我很高兴管道保持如此紧凑。 jsfiddle.net/k06rndjm/2
  • 我的荣幸,保持紧凑也更容易阅读!
【解决方案2】:

您可以将项目阶段与 $dateToString 一起使用,此外它还允许在需要时指定时区

 const data = await Session.aggregate([
  {
    '$match': {
       environment : ObjectID( args.environment ),
       created     : { '$gte': new Date( args.start ), '$lte': new Date( args.end ) }
    }
  },
  {
    $project:{
      visitor: 1,
      createdDate: { $dateToString: { format: "%Y-%m-%d", date: "$created" } },
    }
  },
  {
    $group:{
      _id:{
        date:"$createdDate",visitor:"$visitor"
      },
      count:{$sum:1}
    }
  },
  {
    $project:{
      _id:0,
      date:"$_id.date",
      count:"$count",
    }
  }
])

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-05-17
    • 2013-11-25
    • 1970-01-01
    • 1970-01-01
    • 2021-09-28
    • 2019-04-28
    • 2021-02-21
    • 1970-01-01
    相关资源
    最近更新 更多