我为几乎实时的统计模块创建数据库结构。我想计算不同产品的用户行为:新喜欢,投票,新评论和总活动(投票总数,喜欢等)。
模块需要在过去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:00
到2016-04-14 12:00:00
我可以为此编写查询,还是应该更改数据结构?一个简单的解决方法是将每小时数据存储在独立文档中,但它将包含24倍以上的数据,对于大量产品,它可能会很慢。
答案 0 :(得分:0)
我认为您需要按照您对独立文档中每小时数据的建议更改架构。您还应该为日期使用正确的日期()字段,这样您就可以更灵活地使用基于日期的查询。
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") }}}
])