Cómo generar un valor vacío a partir de resultados agregados con Mongodb
En primer lugar, la función:
static async getInitRegistrationMetric(account) {
// queremos solo el día completo, así que excluimos la fecha actual
const exclude = DateTime.now()
.setZone('utc')
.startOf('day')
.toISODate();
// esto cuenta el número de clientes creados por día
const groupByDate = {
$group: {
_id: {
$dateToString: { format: '%Y-%m-%d', date: '$createdAt' },
},
count: { $sum: 1 },
},
};
// esta es una forma de renombrar (_id, count) a (date, value)
const renameData = {
$project: {
_id: 0,
date: '$_id',
value: '$count',
},
};
// esto se realiza para filtrar los datos, quiero eliminar la fecha nula y el resultado de hoy
const excludeTodayAndNull = {
$match: {
$and: [
{
date: {
$ne: exclude,
},
},
{
date: {
$ne: null,
},
},
],
},
};
// account es el modelo mongoose.
return account.aggregate([groupByDate, renameData, excludeTodayAndNull]);
}
Este código producirá datos como estos:
const data = [
{ date: '2000-10-01', value: 50 },
{ date: '2000-10-03', value: 12 },
{ date: '2000-10-07', value: 112 },
];
El problema es que no tengo valores para el 2º, 4º, 5º y 6º del mes. Mi idea era obligar a Mongo a “crear” valores vacíos para los otros días de la siguiente manera:
const data = [
{ date: '2000-10-01', value: 50 },
{ date: '2000-10-02', value: 0 },
{ date: '2000-10-03', value: 12 },
{ date: '2000-10-04', value: 0 },
{ date: '2000-10-05', value: 0 },
{ date: '2000-10-06', value: 0 },
{ date: '2000-10-07', value: 112 },
];
¿Cómo puedo pedirle a “aggregate” que complete la brecha entre fechas significativas con datos con 0 como valor?
Gracias.
PD: Ya lo hice por código en JS, pero se ve pesado y feo. Intento hacerlo de forma más limpia.
davy.ai
Para rellenar los vacíos entre las fechas significativas con un valor de 0 como dato, puedes utilizar el operador $setUnion en MongoDB.
Primero, crea una colección de todas las fechas distintas dentro del rango especificado utilizando el operador $range.
Luego, utiliza el operador $setUnion para combinar el resultado de la agregación con la colección recién creada y obtener todas las fechas en un solo array.
Finalmente, utiliza los operadores $map y $ifNull para verificar si la fecha existe en el resultado original de la agregación y reemplazar el valor por 0 si no existe.
Aquí tienes un ejemplo de implementación de la solución:
Ten en cuenta que el código anterior asume que deseas llenar los vacíos con 0 para un rango de fechas determinado, que puedes definir cambiando las variables start y end. Si deseas llenar los vacíos para un mes determinado, por ejemplo, puedes ajustar las variables start y end en consecuencia.