Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

177
Vistas
Inserción masiva solo cuando se cumple la condición especificada

Tengo una serie de objetos que se ven así:

 { type: 'foo', value : 2, hashedIdentifier : ASDZXC, createdAt : '2022-02-27T14:17:44.860+00:00' }

Me gustaría insertarlos a granel en una colección de MongoDB. Mi lógica comercial exige que no se creen 2 objetos idénticos en un período de 7 días. Para eso, uso el campo hashedIdentifier para encontrar duplicados, donde createdAt es $gte "hace 7 días", filtro los duplicados de la matriz y luego inserto lo que queda en la matriz.

Estas son 2 consultas DB diferentes, y estoy buscando algo un poco más hermético y atómico.

Estaba mirando updateMany con upsert, pero no pude resolver esto.

¿Hay alguna manera de insertar todos los objetos de la matriz de forma masiva, insertando solo aquellos objetos que no entren en conflicto con la restricción anterior (identificador + rango createdAt)?

  • Un índice único (o único compuesto) no me sirve aquí, ya que quiero habilitar la creación de duplicados después de que haya pasado el intervalo de tiempo (7 días).
  • un TTL en objetos de colección también está fuera de discusión, ya que quiero conservarlos todos, para siempre.
over 4 years ago · Santiago Trujillo
1 Respuestas
Responde la pregunta

0

Una forma de hacerlo es usar una canalización de agregación con $merge . Por ejemplo:

 db.collection.aggregate([ { $group: { _id: "$hashedIdentifier", latestExisting: { $max: "$createdAt" } } }, { $match: { _id: { $in: [ "ASDZXC", "TSSGKE", "SDFKAR" ] } } }, { $group: { _id: 0, existing: { $push: { hashedIdentifier: "$_id", latestExisting: "$latestExisting" } } } }, { $addFields: { newItems: [ { type: "foo", value: 2, hashedIdentifier: "ASDZXC", createdAt: ISODate("2022-03-06T14:18:44.860+00:00") }, { type: "bar", value: 3, hashedIdentifier: "TSSGKE", createdAt: ISODate("2022-03-06T15:17:44.860+00:00") }, { type: "newOne", value: 9, hashedIdentifier: "SDFKAR", createdAt: ISODate("2022-03-06T15:17:44.860+00:00") } ] } }, { $unwind: "$newItems" }, { $project: { existing: { $filter: { input: "$existing", as: "item", cond: { $eq: [ "$$item.hashedIdentifier", "$newItems.hashedIdentifier" ] } } }, newItems: 1, latestExisting: 1 } }, { $project: { existing: {$arrayElemAt: ["$existing", 0]}, newItem: "$newItems" } }, { $project: { delta: { $subtract: [ "$newItem.createdAt", "$existing.latestExisting" ] }, latestExisting: 1, newItem: 1 } }, { $match: { $or: [{ delta: {$gte: 604800000}}, {delta: null}] } }, { $replaceRoot: {newRoot: "$newItem"} }, { $merge: {into: "collection"} } ])

Como puede ver en este ejemplo de patio de recreo.

Primero, agrupamos los documentos existentes por hashedIdentifier , ya que solo nos interesa la última fecha existente. Luego mantenemos los documentos relevantes que coinciden con los que probamos para insertar y los agrupamos en un solo documento. El siguiente paso es agregar todos los elementos nuevos usando $addFields y $unwind , para que sean documentos separados. Ahora solo tenemos que hacer coincidir para cada elemento nuevo, el elemento existente si hay alguno, y probar la condición de diferencia de tiempo (604800000 ms). Los documentos que coinciden con esta condición se pueden $merge de nuevo en la colección como nuevos documentos validados.

over 4 years ago · Santiago Trujillo Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda