Para agentes de IA: hay un índice de documentación disponible en https://www.mongodb.com/es/docs/llms.txt — versiones en markdown de todas las páginas están disponibles agregando .md a cualquier ruta URL.
Docs Menu

$merge (etapa de agregación)

Nota

Esta página describe la etapa $merge, que produce los resultados del pipeline de agregación a una colección. Para el operador $mergeObjects, que fusiona documentos en un solo documento, consulta $mergeObjects.

$merge

Escribe los resultados de la canalización de agregación en una colección especificada. El operador $merge debe ser la última etapa del pipeline.

La etapa $merge:

  • Se puede enviar a una colección en la misma base de datos o en una base de datos diferente.

  • Puede generar salida a la misma colección que se está agregando. Para obtener más información, consulta Salida a la misma colección que se está agregando.

  • Considera los siguientes puntos al usar las etapas $merge o $out en un pipeline de agregación:

    • A partir de MongoDB 5.0, los pipelines con una etapa $merge pueden ejecutarse en nodos secundarios del set de réplicas si todos los nodos del clúster tienen la featureCompatibilityVersion establecida en 5.0 o superior y la preferencia de lectura permite lecturas secundarias.

      • $merge y $out se ejecutan en nodos secundarios, pero las operaciones de escritura se envían al nodo primario.

      • No todas las versiones de los drivers son compatibles con las operaciones $merge enviadas a los nodos secundarios. Para obtener más detalles, consulte la documentación del driver.

    • En versiones anteriores de MongoDB, los pipelines con etapas de $out o $merge siempre se ejecutan en el nodo primario y no se considera la preferencia de lectura.

  • Cree una nueva colección si la colección de salida no existe ya.

  • Puede incorporar resultados (insertar nuevos documentos, fusionar documentos, reemplazar documentos, mantener documentos existentes, fallar la operación, procesar documentos con un pipeline de actualización personalizado) en una colección existente.

  • Puede dar salida a una colección fragmentada. La colección de entrada también se puede fragmentar.

Para una comparación con la etapa $out que también genera los resultados de la agregación en una colección, consulta Comparación de $merge y $out.

Nota

Vistas materializadas on-demand

$merge puede incorporar los resultados del pipeline en una colección de salida existente en lugar de realizar un reemplazo completo de la colección. Esta funcionalidad permite a los usuarios crear vistas materializadas on-demand, donde el contenido de la colección de salida se actualiza de forma incremental cuando se ejecuta el pipeline.

Para obtener más información sobre este caso de uso, consulta Vistas materializadas on-demand así como los ejemplos de esta página.

Las vistas materializadas son distintas de las vistas de solo lectura. Para obtener información sobre la creación de vistas de solo lectura, consulta vistas de solo lectura.

Puedes usar $merge para implementaciones alojadas en los siguientes entornos:

  • MongoDB Atlas: El servicio totalmente gestionado para implementaciones de MongoDB en la nube
  • MongoDB Enterprise: La versión basada en suscripción y autogestionada de MongoDB

  • MongoDB Community: La versión de MongoDB con código fuente disponible, de uso gratuito y autogestionada.

$merge tiene la siguiente sintaxis:

{ $merge: {
into: <collection> -or- { db: <db>, coll: <collection> },
on: <identifier field> -or- [ <identifier field1>, ...], // Optional
let: <variables>, // Optional
whenMatched: <replace|keepExisting|merge|fail|pipeline>, // Optional
whenNotMatched: <insert|discard|fail> // Optional
} }

Por ejemplo:

{ $merge: { into: "myOutput", on: "_id", whenMatched: "replace", whenNotMatched: "insert" } }

Si utilizas todas las opciones por defecto para $merge, incluida la escritura en una colección de la misma base de datos, puedes utilizar la forma simplificada:

{ $merge: <collection> } // Output collection is in the same database

La etapa $merge procesa un documento con los siguientes campos:

Campo
Descripción

La colección de resultados. Especifica una de las siguientes opciones:

  • El nombre de la colección como un string para enviar a una colección en la misma base de datos donde se ejecuta la agregación. Por ejemplo:

    into: "myOutput"

  • El nombre de la base de datos y de la colección en un documento para enviar a una colección en la base de datos especificada. Por ejemplo:

    into: { db:"myDB", coll:"myOutput" }

Si la colección de salida no existe, $merge crea la colección:

  • Para un Set de réplicas o un autónomo, si la base de datos de salida no existe, $merge también crea la base de datos.

  • Para un clúster particionado, la base de datos de salida especificada ya debe existir.

La colección de salida puede ser una colección fragmentada.

Opcional. Campo o campos que funcionan como identificador único de un documento. El identificador determina si un documento de resultados coincide con un documento existente en la colección de salida. Especifica una de las siguientes opciones:

  • Un solo nombre de campo como un string. Por ejemplo:

    on: "_id"

  • Una combinación de campos en un arreglo. Por ejemplo:

    on: [ "date", "customerId" ]

    El orden de los campos en el arreglo no importa y no se puede especificar el mismo campo varias veces.

Para el campo o los campos especificados:

  • Los documentos de resultados de la agregación deben contener el(los) campo(s) especificado(s) en el on, a menos que el campo on sea el campo _id. Si falta el campo _id en un documento de resultados, MongoDB lo agrega automáticamente.

  • Para las implementaciones que ejecutan MongoDB 8.0 y versiones anteriores, los campos especificados para on no pueden faltar ni contener un valor nulo. A partir de MongoDB 8.1, si el índice de soporte no es disperso, el campo o los campos especificados para on pueden faltar o contener un valor nulo.

  • El campo o los campos especificados no pueden contener un valor de arreglo.

$merge requiere un índice único con claves que correspondan a los campos de identificador on. Aunque el orden de la especificación de la clave del índice no importa, el índice único debe contener únicamente los campos on como sus claves.

  • El índice también debe tener la misma intercalación que la de la agregación.

  • El índice único puede ser un índice disperso.

  • El índice único no puede ser un índice parcial.

  • Para las colecciones de salida que ya existen, el índice correspondiente ya debe existir.

El valor por defecto de on depende de la colección de salida:

  • Si la colección de salida no existe, el identificador on debe ser y por defecto es el campo _id. El índice único correspondiente de _id se crea automáticamente.

    • Para utilizar un campo identificador diferente en para una colección que no existe, primero puede crear la colección generando un índice único en el campo(s) deseado(s). Consulta la sección sobre colección de salida no existente para conocer un ejemplo.

    • A partir de MongoDB 8.3, el servidor verifica que el índice _id creado automáticamente coincida con la intercalación de la query. Si las intercalaciones no coinciden, el _id índice no puede proporcionar unicidad a la query, y la query no se ejecutará.

  • Si la colección de salida existente no está particionada, el identificador on se asigna por defecto al campo _id.

  • Si la colección de salida existente es una colección particionada, el identificador on se establece de forma predeterminada en todos los campos de la clave de partición y el campo _id. Si se especifica un identificador de on diferente, el on debe contener todos los campos de la clave de partición.

opcional. El comportamiento de $merge si un documento resultante y un documento existente en la colección tienen el mismo valor para el o los campos on especificados.

Se puede especificar cualquiera de los dos:

  • Una de las cadenas de acción predefinidas:

    • "reemplazar":

      Reemplaza el documento existente en la colección de salida con el documento de resultados coincidente.

      Al realizar una sustitución, el documento de reemplazo no puede dar lugar a una modificación del valor _id o, si la colección de salida está particionada, del valor de la clave de partición. De lo contrario, la operación genera un error.

      Para evitar este error, si el campo on no incluye el campo _id, remueve el campo _id en los resultados de la agregación para evitar el error, como con una etapa $unset precedente, y así sucesivamente.

    • "Mantener existente":

      Mantén el documento existente en la colección de salida.

    • "fusionar" (Predeterminado):

      Fusionar los documentos coincidentes (similar al operador $mergeObjects).

      • Si el documento de resultados contiene campos que no están en el documento existente, se deben agregar estos nuevos campos al documento existente.

      • Si el documento de resultados contiene campos en el documento existente, se deben reemplazar los valores de los campos existentes con los del documento de resultados.

      Por ejemplo, si la colección de salida contiene el documento:

      { _id: 1, a: 1, b: 1 }

      Y los resultados de la agregación contienen el documento:

      { _id: 1, b: 5, z: 1 }

      Entonces, el documento combinado es:

      { _id: 1, a: 1, b: 5, z: 1 }

      Al realizar una fusión, el documento fusionado no puede resultar en una modificación del valor de _id ni, si la colección de salida está particionada, del valor de la clave de partición. De lo contrario, la operación genera un error.

      Para evitar este error, si el campo on no incluye el campo _id, remueve el campo _id en los resultados de la agregación para evitar el error, como con una etapa $unset precedente, y así sucesivamente.

    • "fallo":

      Se debe detener y cancelar la operación de agregación. Cualquier cambio en la colección de salida de documentos anteriores no se revierte.

  • Un pipeline de agregación para actualizar el documento en la colección.

    [ <stage1>, <stage2> ... ]

    El pipeline solo puede consistir en las siguientes etapas:

    El pipeline no puede modificar el valor del campo on. Por ejemplo, si está haciendo coincidir en el campo month, el pipeline no puede modificar el campo month.

    El pipeline whenMatched puede acceder directamente a los campos de los documentos existentes en la colección de salida usando $<field>.

    Para acceder a los campos de los documentos de resultados de agregación, usa cualquiera de las siguientes opciones:

    • La variable $$new de funcionalidad incorporada para acceder al campo. Específicamente, $$new.<field>. La variable $$new solo está disponible si se omite la especificación let.

    • Las variables definidas por el usuario en el campo let.

      Se debe especificar el prefijo del signo de dólar doble ($$) junto con el nombre de la variable en el formato $$<variable_name>. Por ejemplo, $$year. Si la variable está configurada como un documento, también se puede incluir un campo de documento en el formulario $$<variable_name>.<field>. Por ejemplo, $$year.month.

      Para más ejemplos, consulta Usar variables para personalizar la combinación.

opcional. Especifica variables para uso en el pipeline whenMatched.

Especifica un documento con los nombres de las variables y las expresiones de valores:

{ <variable_name_1>: <expression_1>,
...,
<variable_name_n>: <expression_n> }

Si no se especifica, es por defecto { new: "$$ROOT" } (consulta ROOT). El pipeline whenMatched puede acceder a la variable $$new.

Para acceder a las variables en el pipeline whenMatched:

Se debe especificar el prefijo del signo de dólar doble ($$) junto con el nombre de la variable en el formato $$<variable_name>. Por ejemplo, $$year. Si la variable está configurada como un documento, también se puede incluir un campo de documento en el formulario $$<variable_name>.<field>. Por ejemplo, $$year.month.

Para ejemplos, consulte Usar variables para personalizar la combinación.

Opcional. El comportamiento de $merge si un documento de resultado no coincide con un documento existente en la colección de salida.

Puedes especificar una de las cadenas de acción predefinidas:

  • "insert" (Default):

    Inserta el documento en la colección de salida.

  • "descartar":

    Desecha el documento. Específicamente, $merge no inserta el documento en la colección de salida.

  • "fallo":

    Se debe detener y cancelar la operación de agregación. Cualquier cambio ya escrito en la colección de salida no se revierte.

Si el campo _id no está presente en un documento de los resultados de la pipeline de agregación, la etapa $merge lo genera automáticamente.

Por ejemplo, en la siguiente pipeline de agregación, $project excluye el campo _id de los documentos pasados a $merge. Cuando $merge guarda estos documentos en el "newCollection", $merge genera un nuevo campo _id y un valor.

db.movies.aggregate( [
{ $project: { _id: 0 } },
{ $merge : { into : "newCollection" } }
] )

La operación $merge crea una nueva colección si la colección de salida especificada no existe.

  • La colección de salida se crea cuando $merge guarda el primer documento a la colección y es visible inmediatamente.

  • Si la agregación falla, cualquier guardado completado por el $merge antes del error no se revertirá.

Nota

Para un Set de réplicas o un autónomo, si la base de datos de salida no existe, $merge también crea la base de datos.

Para un clúster particionado, la base de datos de salida especificada ya debe existir.

Si la colección de salida no existe, $merge requiere que el identificador on sea el campo _id. Para utilizar un valor de campo on diferente para una colección que no existe, primero puedes crear la colección creando un índice único en el(los) campo(s) deseado(s). Por ejemplo, si la colección de salida newDailyCommentCount no existe y deseas especificar el campo commentDate como el identificador on:

db.newDailyCommentCount.createIndex(
{ commentDate: 1 }, { unique: true } )
db.comments.aggregate( [
{ $match: { date: { $gte: new Date("2002-01-01"),
$lt: new Date("2002-02-01") } } },
{ $group: { _id: { $dateToString: { format: "%Y-%m-%d",
date: "$date" } }, count: { $sum: 1 } } },
{ $project: { _id: 0, commentDate: { $toDate: "$_id" },
count: 1 } },
{ $merge : { into : "newDailyCommentCount",
on: "commentDate" } }
] )

La etapa $merge puede generar una salida a una colección fragmentada. Cuando la colección de salida está particionada, $merge usa el campo _id y todos los campos de clave de partición como el identificador por defecto. Si anulas el valor por defecto, el identificador en debe incluir todos los campos de la clave de partición:

{ $merge: {
into: "<shardedColl>" or { db:"<sharding enabled db>", coll: "<shardedColl>" },
on: [ "<shardkeyfield1>", "<shardkeyfield2>",... ], // Shard key fields and any additional fields
let: <variables>, // Optional
whenMatched: <replace|keepExisting|merge|fail|pipeline>, // Optional
whenNotMatched: <insert|discard|fail> // Optional
} }

Por ejemplo, se debe usar el método sh.shardCollection() para crear una nueva colección particionada moviesByYearAndRating con el campo rated como clave de partición.

sh.shardCollection(
"sample_mflix.moviesByYearAndRating", // Namespace of the collection to shard
{ rated: 1 }, // Shard key
);

La colección moviesByYearAndRating contendrá documentos con estadísticas de películas por año (campo year) y clasificación de contenido (clave de partición); específicamente, el identificador en es ["year", "rated"] (el orden de los campos no importa). Debido a que $merge requiere un índice único con claves que correspondan a los campos de identificador en, crea el índice único (el orden de los campos no importa): [1]

db.moviesByYearAndRating.createIndex(
{ rated: 1, year: 1 }, { unique: true } )

Con la colección particionada moviesByYearAndRating y el índice único creado, se puede utilizar $merge para enviar los resultados de la agregación a esta colección, coincidiendo en [ "year", "rated" ] como en este ejemplo:

db.movies.aggregate( [
{ $match: { rated: { $ne: null }, year: { $ne: null } } },
{ $group: {
_id: { year: "$year", rated: "$rated" },
movieCount: { $sum: 1 } } },
{ $project: { _id: 0, year: "$_id.year", rated: "$_id.rated",
movieCount: 1 } },
{ $merge: { into: "moviesByYearAndRating",
"on": [ "year", "rated" ], whenMatched: "replace",
whenNotMatched: "insert" } }
] )
[1]

El método sh.shardCollection() también puede crear un índice único en la clave de partición cuando se pasa la opción { unique: true } si: la clave de partición es basada en rango, la colección está vacía y no existe un índice único en la clave de partición.

En el ejemplo anterior, debido a que el identificador on es la clave de partición y otro campo, se requiere una operación separada para crear el índice correspondiente.

$merge puede reemplazar un documento existente en la colección de resultados si los resultados de la agregación contienen uno o varios documentos que coinciden según la especificación. Por lo tanto, $merge puede reemplazar todos los documentos en la colección existente si los resultados de la agregación incluyen documentos coincidentes para todos los documentos existentes en la colección y especificar "reemplazar" para whenMatched.

Sin embargo, para reemplazar una colección existente independientemente de los resultados de la agregación, se debe usar $out en su lugar.

Los $merge errores ocurren si el $merge resulta en un cambio en el valor _id de un documento existente.

Tip

Para evitar este error, si el campo on no incluye el campo _id, remueve el campo _id en los resultados de la agregación para evitar el error, como con una etapa $unset precedente, y así sucesivamente.

Además, para una colección fragmentada, $merge también genera un error si provoca un cambio en el valor de clave de fragmentación de un documento existente.

Cualquier guardado completado por el $merge antes del error no se revertirá.

Si el índice único utilizado por $merge para los campo(s) se descartan a mitad de la agregación, no hay garantía de que la agregación se detenga. Si la agregación continúa, no hay garantía de que los documentos no tengan valores duplicados en el campo on.

Si el $merge intenta guardar un documento que viola algún índice único en la colección de salida, la operación genera un error. Por ejemplo:

Si su colección utiliza validación de esquemas y tiene validationAction configurado en error, insertar un documento no válido o actualizar un documento con valores no válidos con $merge genera un MongoServerError y el documento no se escribe en la colección de destino. Si hay varios documentos no válidos, solo el primer documento no válido que se encuentre generará un error. Todos los documentos válidos se guardan en la colección de destino, y todos los documentos no válidos fallan al intentar guardarse.

$merge inserta el documento directamente en la colección de salida cuando se cumplen todas las condiciones siguientes:

  • El valor de whenMatched es una pipeline de agregación.

  • El valor de whenNotMatched es insert.

  • No hay coincidencia para un documento en la colección de salida.

Con la introducción de $merge, MongoDB proporciona dos etapas, $merge y $out, para escribir los resultados de la pipeline de agregación en una colección:

$merge
  • Se puede enviar a una colección en la misma base de datos o en una base de datos diferente.
  • Se puede enviar a una colección en la misma base de datos o en una base de datos diferente.
  • Cree una nueva colección si la colección de salida no existe ya.
  • Cree una nueva colección si la colección de salida no existe ya.
  • Puede incorporar resultados (insertar nuevos documentos, fusionar documentos, reemplazar documentos, mantener documentos existentes, fallar la operación, procesar documentos con un pipeline de actualización personalizado) en una colección existente.

    Consulta también Reemplazo de documentos ($merge) vs Reemplazo de colección ($out).

  • Se debe reemplazar por completo la colección de salida si ya existe.
  • Puede dar salida a una colección fragmentada. La colección de entrada también se puede fragmentar.
  • No se puede enviar a una colección particionada. Sin embargo, la colección de entrada se puede particionar.
  • Corresponde a las instrucciones SQL:

    • MERGE.

    • INSERT INTO T2 SELECT FROM T1.

    • SELECT INTO T2 FROM T1.

    • Crear/actualizar vistas materializadas.

  • Corresponde a la instrucción SQL:

    • INSERT INTO T2 SELECT FROM T1.

    • SELECT INTO T2 FROM T1.

Advertencia

Cuando $merge genera resultados en la misma colección que se está agregando, los documentos pueden actualizarse varias veces o la operación puede resultar en un bucle infinito. Este comportamiento ocurre cuando la actualización realizada por $merge cambia la ubicación física de los documentos almacenados en el disco. Cuando la ubicación física de un documento cambia, $merge puedes verlo como un documento completamente nuevo, lo que resulta en actualizaciones adicionales. Para obtener más información sobre este comportamiento, consulta Halloween Problem.

$merge puede generar salida a la misma colección que se está agregando. También puedes exportar a una colección que aparezca en otras etapas del pipeline, como $lookup.

Restricciones
Descripción

La pipeline de agregación no puede usar $merge dentro de una transacción.

Un pipeline de agregación no puede usar $merge para generar una colección de series de tiempo.

ver definición
Separado de la vista materializada

Una definición de vista no puede incluir la etapa $merge. Si la definición de la vista incluye una pipeline anidada (por ejemplo, la definición de la vista incluye la etapa $facet), esta restricción de la etapa $merge también se aplica a las pipelines anidadas.

$lookup etapa

El pipeline anidado de la etapa $lookup no puede incluir la etapa $merge.

$facet etapa

El pipeline anidado de la etapa $facet no puede incluir la etapa $merge.

El pipeline anidado de la etapa $unionWith no puede incluir la etapa $merge.

"linearizable" readConcern

La etapa $merge no se puede utilizar junto con el nivel de consistencia de lectura "linearizable". Es decir, si se especifica el nivel de consistencia de lectura "linearizable" para db.collection.aggregate(), no se puede incluir la etapa $merge en el pipeline.