sql >> Base de Datos >  >> NoSQL >> MongoDB

MongoDB Schema Design - Votación en publicaciones

La forma común de realizar un seguimiento de los recuentos de votos en general sería mantener el número de votos en el documento de publicación y actualizarlo de forma atómica al enviar un nuevo valor a la matriz de votos.

Como se trata de una única actualización, tiene la garantía de que el recuento coincidirá con el número de elementos de la matriz.

Si la cantidad de agregaciones es fija y el sitio está muy ocupado, podría extender este paradigma e incrementar contadores adicionales, como uno para el mes, el día y la hora, pero eso podría salirse de control muy rápidamente. Entonces, en su lugar, podría usar el nuevo Marco de agregación (disponible en la versión de desarrollo 2.1.2, estará en producción en la versión 2.2. Es más fácil de usar que Map/Reduce y le permitirá hacer los cálculos que desee de manera muy simple, especialmente si tiene cuidado de almacenar las fechas de su voto como Tipo ISODate().

La canalización típica para la consulta de agregación de los principales ganadores de votos este mes podría verse así:

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

Esto limita la entrada a la tubería a las publicaciones que tienen votos haciendo coincidir las fechas de votación con el mes que está contando, "desenrolla" la matriz para obtener un documento por voto y luego hace un equivalente de "agrupar por" sumando todos los votos para cada título (Supongo que el título es único). Luego ordena de forma descendente por número de votos y limita la salida a los diez primeros.

También tiene la posibilidad de agregar votos por día (por ejemplo) para ese mes para ver qué días son más activos para votar:

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