2016-04-14 61 views
0

我正在为几乎实时的统计模块创建数据库结构。我想统计不同产品的用户行为:新的喜欢,投票,新评论和总活动(总票数,喜欢等)。MongoDB中重叠日期的聚合查询

该模块需要在过去的8,16或24小时内发送最多的活动的 N产品。 我的第一个想法是为一个文件下面的模式:

{ 
    "_id" : ObjectId("570e37d0db8c0897d651509c"), 
    "date" : "2016-04-13", 
    "trackId" : 35, 
    "count" : { 
     "hour_1" : { 
      "total" : 120, 
      "downVote" : 35, 
      "newComment" : 26, 
      "upVote" : 34, 
      "like" : 25 
     }, 
     "hour_2" : { 
      "total" : 124, 
      "downVote" : 32, 
      "like" : 28, 
      "upVote" : 33, 
      "newComment" : 31 
     }, 
     // ... 
     "hour_24" : { 
      "total" : 119, 
      "downVote" : 42, 
      "newComment" : 30, 
      "upVote" : 31, 
      "like" : 16 
     } 
    } 
} 

在这种情况下,我有X产品X文件在一天与此查询我什么,我需要快速维伊获取数据。

db.getCollection('HourlyStat') 
    .aggregate([ 
    {$match: {date: '2016-04-13'}}, 
    { 
     $project: {'trackId': "$trackId", 
     count: { 
     $sum: ["$count.hour_1.total", "$count.hour_2.total", ..., "$count.hour_8.total"] } 
     } 
    }, 
    {$sort: {'count': -1}}, {$limit: 10} 
    ]) 

不幸的是,这是不适用于包括两天的时间段。 例如:从2016-04-13 12:00:002016-04-14 12:00:00

我可以为此编写一个查询,或者我应该更改我的数据结构吗?一个简单的解决方法是将小时数据存储在独立的文档中,但它将包含多达24倍的数据,而对于大量的产品,它可能会很慢。

+0

好了,你就需要为每个时隙运行多个聚集查询,并在应用程序中合并返回文档的情况下。 – Saleem

+0

@Saleem这不是一个可以接受的解决方案,因为在这种情况下,应用程序服务器需要处理大量的数据,消耗内存。 – Festo

回答

0

我认为你需要改变你的模式,因为你建议独立文档中的小时数据。您还应该为日期使用正确的Date()字段,这将使您在基于日期的查询中变得更加灵活。

db.getCollection('HourlyStat') 
    .aggregate([ 
    {$match: {date: {$gt: new Date(new Date()-1000*60*60*24)}}} 
    //... 
    ]) 

如果它更容易,你也可以生成客户端搜索的开始结束时间,而不是限制到最后n个小时,例如。这有一个简单的寻找查询的优势(我喜欢简单的查询)

db.getCollection('dates') 
    .aggregate([ 
    {$match: {date: {$gte: ISODate("2016-04-13T09:00:00.000+0000"), $lt: ISODate("2016-05-16T20:00:00.000+0000") }}} 
    ])