Soy nuevo aquí con MongoDB. Necesito su ayuda. Quiero eliminar varios documentos de una colección en función de ciertas condiciones, es decir, agruparlos según empID y eliminar los registros excepto el último registro para ese empID.
Supongamos que mi conjunto de datos se ve así:
[ { _id: 1, employeeId: "50052196", name: "abc", lastUpdatedOn: ISODate("2022-01-10T10:25:38.859+00:00") }, { _id: 2, employeeId: "50052197", name: "xyz", lastUpdatedOn: ISODate("2022-01-17T10:25:38.859+00:00") }, { _id: 3, employeeId: "50052198", name: "pqr", lastUpdatedOn: ISODate("2022-01-17T10:25:38.859+00:00") }, { _id: 4, employeeId: "50052196", name: "abc", lastUpdatedOn: ISODate("2022-01-12T11:30:58.435+00:00") }, { _id: 5, employeeId: "50052196", name: "abc", lastUpdatedOn: ISODate("2022-01-15T15:45:00.159+00:00") } ]
En el conjunto de datos anterior, employeeID : 50052196
es un documento duplicado que se insertó periódicamente junto con el campo lastUpdatedOn
. Como lastUpdatedOn
no es más que la fecha de creación del registro/documento.
Ahora, quiero mantener el documento con el valor lastUpdatedOn más reciente, es decir, lastUpdatedOn:2022-01-15T15:45:00.159+00:00
para employeeID : 50052196
.
Revisé la documentación de MongoDB y descubrí que no podemos escribir la consulta de eliminación junto con la operación de agrupar y ordenar. O si elegimos Aggregate Pipeline, entonces no podemos eliminar documentos dentro del agregado. Estaba revisando la opción de Bulk.find.remove()
, pero nuevamente no puedo averiguar cómo agrupar el employeeId.
Otro enfoque que tenía en mente, basado en alguna condición, agregaré un campo, es decir, isActive: true
. Y usando la operación normal deleteMany()
puedo eliminar isActive: false
. Pero según la política no puedo modificar los documentos. La operación de inserción en la colección es manejada por una aplicación de terceros, que no podemos modificar.
Como los documentos son más grandes en número, y quería escribir un código que consumiría menos tiempo y recursos al mismo tiempo, debería cumplir con las mejores prácticas. La ayuda es muy apreciada. ¿Puede alguien sugerirme una buena opción para abordar esta situación? La ayuda es muy apreciada.
NOTA: El mismo tipo de código de eliminación que tengo que escribir para varias colecciones de MongoDB. Es una especie de guión de limpieza que estoy pensando en escribir.
Puede usar cualquier tubería que desee y agregar una etapa de $out al final, esto sobrescribirá la colección elegida.
por ejemplo:
db.collection.aggregate([ { $sort: { lastUpdatedOn: -1 } }, { $group: { _id: "$employeeId", root: { $first: "$$ROOT" } } }, { $replaceRoot: { newRoot: "$root" } }, { $out: "collection" } ])
Una forma más controlada en el código, iterar usuario por usuario:
const userIds = await db.collection.distinct('employeeId'); for (let i = 0; i < userIds.length; i++) { const userId = userIds[i]; const employeeRecords = await db.collection.find({ 'employeeId': userId }).sort({ lastUpdatedOn: -1 }).toArray(); employeeRecords.pop(); await db.collection.deleteMany({ _id: { $in: employeeRecords.map(v => v._id) } }); }
(esto debería ejecutarse en paralelo. Está escrito en un bucle for para mayor claridad)