Tengo un gran conjunto de datos MongoDB de alrededor de 34 gb y estoy usando Fastify y Mongoose para la API. Quiero recuperar toda la lista de userUuid únicos del rango de fechas. Probé el método distinto de Mongoose:
Estos son mis filtros:
let filters = { applicationUuid: opts.applicationUuid, impressions: { $gte: opts.impressions }, date: { $gte: moment(opts.startDate).tz('America/Chicago').format(), $lt: moment(opts.endDate).tz('America/Chicago').format() } }Esta es mi función Mongoose distinta:
return await Model.distinct("userUuid", filters)Este método devolverá una matriz con userUuid único basado en los filtros.
Esto funciona bien para conjuntos de datos pequeños, pero tiene un límite de memoria de 16 MB cuando se trata de conjuntos de datos grandes.
Por lo tanto, probé el método agregado para lograr resultados similares, después de leer que está mejor optimizado. Sin embargo, el mismo objeto de filtros anterior no funciona dentro de la tubería de coincidencia porque el agregado no acepta la fecha de la cadena que viene como resultado del momento; pero solo se acepta la fecha de JavaScript. Sin embargo, la fecha de JavaScript ignora todas las zonas horarias ya que está basada en Unix.
Esta es mi función agregada para obtener valores distintos basados en filtros.
return await Model.aggregate( [ { $match: filters }, { $group: { _id: {userUuid: "$userUuid" } } } ] ).allowDiskUse(true);Como dije, $match no funciona con el momento, sino solo con la nueva fecha (opts.startDate), sin embargo, la nueva fecha de JavaScript ignora la zona horaria del momento. Tampoco tiene una zona horaria nativa adecuada. ¿Alguna idea sobre cómo lograr esta matriz de identificaciones únicas basadas en filtros con Mongoose?
Esta es la solución que se me ocurrió y funciona bastante bien con respecto al rendimiento. Utilice esta solución para grandes conjuntos de datos:
let filters = { applicationUuid: opts.applicationUuid, impressions: { $gte: opts.impressions }, $expr: { $and: [ { $gte: [ '$date', { $dateFromString: { dateString: opts.startDate, timezone: 'America/Chicago', }, }, ], }, { $lt: [ '$date', { $dateFromString: { dateString: opts.endDate, timezone: 'America/Chicago', }, }, ], }, ], }, } return Model.aggregate([ { $match: filters }, { $group: { _id: '$userUuid', }, }, { $project: { _id: 0, userUuid: '$_id', }, }, ]) .allowDiskUse(true)Lo que devolverá una lista de identificadores únicos, es decir
[ { userUuid: "someId" }, { userUuid: "someId" } ]Use el siguiente método en un conjunto de datos pequeño que es más conveniente:
let filters = { applicationUuid: opts.applicationUuid, impressions: { $gte: opts.impressions }, date: { $gte: opts.startDate, $lte: opts.endDate } } return Model.distinct("userUuid", filters)Lo cual devolverá el siguiente resultado:
[ "someId", "someOtherId" ]