Estoy tratando de obtener todos los pedidos entre dos fechas, agruparlos por día de la semana y luego promediarlos. Actualmente el código se ve así:
export const getOrderValuesBetweenTwoDates = async ( from: number, to: number, ) => { // from, and to are guaranteed to be Mondays, 00:00 const orders = await OrderModel.find({ createdAt: { $lt: to, $gte: from }, }).exec(); const totalOfDaysOfWeek = [0, 0, 0, 0, 0, 0, 0]; orders.forEach((order) => { const daysSinceFrom = (order.createdAt - from) / dayInMilliseconds; const dayOfWeek = Math.floor(daysSinceFrom) % 7; totalOfDaysOfWeek[dayOfWeek] = (totalOfDaysOfWeek[dayOfWeek] || 0) + order.value; }); const numberOfWeeks = Math.floor((to - from) / dayInMilliseconds / 7); const averageOfDaysOfWeek = totalOfDaysOfWeek.map((v) => Number((v / numberOfWeeks).toFixed(2)), ); return averageOfDaysOfWeek; };Sin embargo, esto no es realmente eficaz, y supongo que si pudiera escribirse en conjunto, lo sería. ¿Es posible convertir lo anterior en agregación?
Entrada de muestra (2 semanas):
[ // 1st mon (total 5) { createdAt: 345600000, value: 2 }, { createdAt: 345600000, value: 3 }, // 1st tue { createdAt: 432000000, value: 1 }, // 1st wed { createdAt: 518400000, value: 1 }, // 1st thu { createdAt: 604800000, value: 1 }, // 1st fri { createdAt: 691200000, value: 1 }, // 1st sat { createdAt: 777600000, value: 1 }, // 1st sun (2 total) { createdAt: 864000000, value: 2 }, // 2nd mon (1 total) { createdAt: 950400000, value: 1 }, // 2nd tue { createdAt: 1036800000, value: 1 }, // 2nd wed { createdAt: 1123200000, value: 1 }, // 2nd thu { createdAt: 1209600000, value: 1 }, // 2nd fri { createdAt: 1296000000, value: 1 }, // 2nd sat { createdAt: 1382400000, value: 1 }, // 2nd sun (4 total) { createdAt: 1468800000, value: 1 }, { createdAt: 1468800000, value: 1 }, { createdAt: 1468800000, value: 2 }, ]En el ejemplo anterior, he creado 2 casos especiales, para el lunes y el domingo. Hay varios pedidos para esos días.
Para el primer lunes hay un pedido con valor 2, y 3, hasta 5 en total. Para el segundo lunes solo hay un pedido con valor 1. El promedio debe ser 3.
Para el domingo, el primero, hay un pedido con valor 2, y para el segundo domingo, hay 3 pedidos con un valor total de 4. Espero que el promedio sea 3.
Espero que el resultado sea [3,1,1,1,1,1,3]
$sum para obtener la suma del mismo día de la semanaWeekDay en la salida será un número entre 1 (domingo) y 7 (sábado).
pruébalo en mongoPlayground
db.collection.aggregate([ { "$addFields": { createdAt: { "$dateToString": { "date": { "$toDate": "$createdAt" }, "format": "%Y-%m-%d" } } } }, { "$group": { "_id": "$createdAt", "value": { "$sum": "$value" } } }, { "$addFields": { "createdAt": { $dayOfWeek: { "$toDate": "$_id" } } } }, { "$group": { "_id": "$createdAt", "average": { "$avg": "$value" } } }, { "$project": { _id: 0, weekDay: "$_id", average: 1 } } ])