MongoDB
 sql >> Base de données >  >> NoSQL >> MongoDB

MongoDB Schema Design - Vote sur les publications

La façon courante de suivre le nombre de votes dans l'ensemble serait de conserver le nombre de votes dans le document de publication et de le mettre à jour de manière atomique lors de la transmission d'une nouvelle valeur au tableau des votes.

Puisqu'il s'agit d'une seule mise à jour, vous avez la garantie que le nombre correspondra au nombre d'éléments du tableau.

Si le nombre d'agrégations est fixe et que le site est très occupé, vous pouvez étendre ce paradigme et incrémenter des compteurs supplémentaires, comme un pour le mois, le jour et l'heure, mais cela pourrait devenir incontrôlable très rapidement. Donc, à la place, vous pouvez utiliser le nouveau Cadre d'agrégation (disponible dans la version dev 2.1.2, sera en production dans la version 2.2. Il est plus simple à utiliser que Map/Reduce et il vous permettra de faire les calculs que vous voulez très simplement surtout si vous prenez soin de stocker vos dates de vote comme Type ISODate().

Un pipeline typique pour une requête d'agrégation pour les meilleurs collecteurs de votes ce mois-ci pourrait ressembler à ceci :

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}
] );

Cela limite l'entrée dans le pipeline aux messages qui ont des votes en faisant correspondre les dates de vote au mois que vous comptez, "déroule" le tableau pour obtenir un document par vote, puis fait un équivalent "grouper par" résumant tous les votes pour chaque titre (Je suppose que le titre est unique). Il trie ensuite par ordre décroissant de nombre de votes et limite la sortie aux dix premiers.

Vous avez également la possibilité de regrouper les votes par jour (par exemple) pour ce mois afin de voir quels jours sont les plus actifs pour voter :

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}
] );