Soy un principiante en express y mongoDB. Estaba trabajando en una tarea en la que tengo un modelo llamado ventas del tipo:
{ userName : String, amount : Number, date : Date }Ahora tengo que crear una API que debe tener un parámetro de 3 tipos: "diario", "semanal", "mensual". Si el parámetro es
diariamente: luego tengo que enviar estadísticas (suma de la cantidad) en función de cada hora del día desde la tabla de ventas.
semanalmente, luego tengo que enviar estadísticas en función de cada día de la semana
mensual - entonces tengo que enviar estadísticas sobre la base de cada día del mes
Después de pensar en algo de lógica, se me ocurrió esto:
Pude hacer las estadísticas diarias pero también se ve complejo
app.get("/fetchSales/:id",async (req, res)=>{ const { id } = req.params; const allSales = await sales.find({}); const dates = []; for(i in allSales){ let date = allSales[i].date.toISOString().replace('Z', '').replace('T', ''); const dateFormat = dayjs(date); dateFormat.amount = allSales[i].amount; dates.push(dateFormat); } if(id === "daily") { const stats = {}; for(let hour = 0; hour < 24; hour++) { let sum = 0 for (x in dates) { if (dates[x]["$H"] === hour) sum += dates[x].amount } stats[hour] = sum; } res.send(stats); } })Pero en el futuro tengo que usar varios bucles y no se ve bien. He leído que tal vez las consultas agregadas podrían ayudarme.
estructura días js me da es -
d { '$L': 'en', '$d': 2021-01-13T13:00:00.000Z, '$x': {}, '$y': 2021, '$M': 0, '$D': 13, '$W': 3, '$H': 18, '$m': 30, '$s': 0, '$ms': 0, amount: 1700 //added on my own// }Alguna estructura de salida que quiero - para diario
{ 0: 0$, 1: 0$, 2: 24$, ... 23: 2$ }¿Alguna idea de cómo puedo lidiar con esto?
Puede crear su condición de consulta en función de la entrada, pero deje que Mongodb haga el trabajo pesado:
app.get("/fetchSales/:id", async (req, res) => { const {id} = req.params; const groupCondition = { sum: {$sum: 1} }; if (id === 'monthly') { groupCondition._id = {$week: '$date'}; } else if (id === 'weekly') { groupCondition._id = {$dayOfMonth: '$date'}; } else if (id === 'weekly') { groupCondition._id = {$hour: '$date'}; } else { // can this happen? what to do here. } const allSales = await sales.aggregate([ { $group: groupCondition }, { $sort: { _id: 1 } } ]); });Tenga en cuenta que esto no devolverá días/semanas/horas con un recuento de documentos de 0, tendrá que insertarlos manualmente a través de la canalización o en el código.
Para realmente $group por fecha completa y no por una determinada hora / día general, debe usar esto:
app.get("/fetchSales/:id", async (req, res) => { const {id} = req.params; const groupCondition = { _id: {year: {$year: '$date'}, $month: {'$month': "$date"}, week: {'$week': "$date"} }, sum: {$sum: 1}, date: {$first: '$date'} //for sorting }; switch (id) { case 'weekly': groupCondition._id.$dayOfMonth = {$dayOfMonth: '$date'}; case 'daily': groupCondition._id.$hour = {$hour: '$date'}; } const allSales = await sales.aggregate([ { $group: groupCondition }, { $sort: { date: 1 } }, { $project: { _id: 1, sum: 1 } } ]); });Esto le dará documentos en esta estructura:
[ { _id: { year: 2020, month: 5, week: 13, day: 22, hour: 5}, sum: 50 } ]