跟踪总体投票计数的常见方法是将投票数保留在帖子文档中,并在将新值推送到投票数组时自动更新投票数。
由于这是一次更新,因此可以保证计数与数组中的元素数量相匹配。
如果聚合的数量是固定的并且站点非常繁忙,您可以扩展此范例并增加额外的计数器,例如一个月、一天和一小时的计数器,但这可能很快就会失控。所以你可以使用新的聚合框架 http://docs.mongodb.org/manual/reference/aggregation/(在 2.1.2 开发版本中可用,将在 2.2 版本中投入生产。它比 Map/Reduce 使用更简单,并且它允许您非常简单地进行您想要的计算,特别是如果您小心地将投票日期存储为ISODate() 类型。
本月得票最高者的聚合查询的典型管道可能如下所示:
today = new Date();
thisMonth = new Date(today.getFullYear(),today.getMonth());
thisMonthEnd = new Date(today.getFullYear(),today.getMonth()+1);
db.posts.aggregate( [
{$match: { "Votes.votedate": {$gte:thisMonth, $lt:thisMonthEnd} } },
{$unwind: "$Votes" },
{$match: { "Votes.votedate": {$gte:thisMonth, $lt:thisMonthEnd} } },
{$group: { _id: "$title", votes: {$sum:1} } },
{$sort: {"votes": -1} },
{$limit: 10}
] );
这会将管道的输入限制为通过将投票日期与您正在计票的月份进行匹配来获得投票的帖子,“展开”数组以获取每个投票的一个文档,然后执行“分组依据”等效操作,汇总每个标题的所有投票(我假设标题是唯一的)。然后,它按票数降序排序,并将输出限制为前十。
您还可以按天(例如)汇总该月的投票,以查看哪一天投票最活跃:
db.posts.aggregate( [
{$match: { "Votes.votedate": {$gte:thisMonth, $lt:thisMonthEnd} } },
{$unwind: "$Votes" },
{$match: { "Votes.votedate": {$gte:thisMonth, $lt:thisMonthEnd} } },
{$project: { "day" : { "$dayOfMonth" : "$Votes.votedate" } } },
{$group: { _id: "$day", votes: {$sum:1} } },
{$sort: {"votes": -1} },
{$limit: 10}
] );