全体的な投票数を追跡する一般的な方法は、投稿ドキュメントの投票数を保持し、新しい値を投票配列にプッシュするときにそれをアトミックに更新することです。
これは単一の更新であるため、カウントが配列内の要素の数と一致することが保証されます。
集計の数が固定されていて、サイトが非常に混雑している場合は、このパラダイムを拡張して、月、日、時間などの追加のカウンターを増やすことができますが、すぐに手に負えなくなる可能性があります。したがって、代わりに、新しい AggregationFramework を使用できます。 (2.1.2 devリリースで利用可能で、リリース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}
] );
これにより、パイプラインへの入力が、投票日をカウントしている月に一致させることで投票がある投稿に制限され、配列を「巻き戻し」て投票ごとに1つのドキュメントを取得し、各タイトルのすべての投票を合計する「groupby」に相当します。 (タイトルは一意だと思います)。次に、投票数の降順で並べ替え、出力を最初の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}
] );