MongoDB
 sql >> Database >  >> NoSQL >> MongoDB

Progettazione di schemi MongoDB - Votazione sui post

Il modo più comune per tenere traccia del conteggio dei voti in generale sarebbe quello di mantenere il numero di voti nel documento del post e di aggiornarlo atomicamente quando si inserisce un nuovo valore nell'array dei voti.

Poiché si tratta di un singolo aggiornamento, hai la garanzia che il conteggio corrisponderà al numero di elementi nell'array.

Se il numero di aggregazioni è fisso e il sito è molto occupato potresti estendere questo paradigma e incrementare contatori aggiuntivi, come uno per mese, giorno e ora, ma ciò potrebbe sfuggire di mano molto rapidamente. Quindi, invece, potresti usare il nuovo Quadro di aggregazione (disponibile nella versione 2.1.2 dev, sarà in produzione nella versione 2.2. È più semplice da usare di Map/Reduce e ti permetterà di fare i calcoli che vuoi in modo molto semplice soprattutto se hai cura di memorizzare le date del tuo voto come tipo ISODate().

La pipeline tipica per la query di aggregazione per i migliori votanti di questo mese potrebbe assomigliare a questa:

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

Questo limita l'input alla pipeline ai post che hanno voti facendo corrispondere le date di voto al mese che stai contando, "srotola" l'array per ottenere un documento per voto e quindi esegue un "raggruppa per" equivalente sommando tutti i voti per ogni titolo (Suppongo che il titolo sia unico). Quindi ordina decrescente per numero di voti e limita l'output ai primi dieci.

Hai anche la possibilità di aggregare i voti per giorno (ad esempio) per quel mese per vedere quali giorni sono più attivi per votare:

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