MongoDB
 sql >> Datenbank >  >> NoSQL >> MongoDB

MongoDB-Schemadesign – Abstimmung über Beiträge

Die übliche Art, die Anzahl der Stimmen insgesamt zu verfolgen, wäre, die Anzahl der Stimmen im Post-Dokument zu behalten und sie atomar zu aktualisieren, wenn ein neuer Wert in das Stimmen-Array verschoben wird.

Da es sich um eine einzelne Aktualisierung handelt, ist garantiert, dass die Anzahl mit der Anzahl der Elemente im Array übereinstimmt.

Wenn die Anzahl der Aggregationen festgelegt ist und die Website sehr ausgelastet ist, könnten Sie dieses Paradigma erweitern und zusätzliche Zähler erhöhen, z. B. einen für Monat, Tag und Stunde, aber das könnte sehr schnell außer Kontrolle geraten. Stattdessen könnten Sie also das neue Aggregation Framework verwenden (verfügbar in der Entwicklerversion 2.1.2, wird in Version 2.2 in Produktion sein. Es ist einfacher zu verwenden als Map/Reduce und ermöglicht es Ihnen, die gewünschten Berechnungen sehr einfach durchzuführen, insbesondere wenn Sie darauf achten, Ihre Abstimmungsdaten als zu speichern Typ ISODate().

Eine typische Pipeline für Aggregationsabfragen für Top-Stimmensammler in diesem Monat könnte etwa so aussehen:

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

Dadurch wird die Eingabe in die Pipeline auf Posts beschränkt, die Stimmen haben, indem sie die Abstimmungsdaten mit dem Monat abgleichen, den Sie zählen, das Array wird "entfaltet", um ein Dokument pro Stimme zu erhalten, und führt dann ein "Gruppieren nach"-Äquivalent durch, das alle Stimmen für jeden Titel zusammenfasst (Ich gehe davon aus, dass der Titel eindeutig ist). Es sortiert dann absteigend nach Anzahl der Stimmen und begrenzt die Ausgabe auf die ersten zehn.

Sie haben auch die Möglichkeit, Stimmen pro Tag (zum Beispiel) für diesen Monat zusammenzufassen, um zu sehen, an welchen Tagen am aktivsten abgestimmt wird:

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