Make the MongoDB docs better! We value your opinion. Share your feedback for a chance to win $100.
Click here >
Docs Menu
Docs Home
/ /

$merge (etapa de agregación)

Nota

Esta página describe el $merge etapa, que arroja los resultados del pipeline de agregación en una colección. Para el 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 específica. El $merge operador debe ser la última etapa de la canalización.

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 la salida en la misma colección que se está agregando. Para obtener más información, consulte Generar la salida en 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 se utilizan todas las opciones predeterminadas para $merge, incluida la escritura en una colección en la misma base de datos, puede 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. Especifique uno de los siguientes:

  • 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" ]
    The order of the fields in the array does not matter, and you cannot specify the same field multiple times.

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.

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

$merge Requiere un índice único con claves que correspondan a los campos identificadores. Aunque el orden de la especificación de la clave del índice no importa, el índice único solo debe contener los on campos como 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.

  • 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 fragmentada, el identificador on se asigna por defecto a todos los campos de la clave de fragmentación y al campo _id. Si se especifica un identificador de on diferente, el on debe contener todos los campos de la clave de fragmentación.

Opcional. El comportamiento de $merge si un documento de resultado y un documento existente en la colección tienen el mismo valor para el campo o campos especificados.

Se puede especificar cualquiera de los dos:

  • Una de las cadenas de acción predefinidas:

    Acción
    Descripción

    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 anterior, y así sucesivamente.

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

    "merge" (por defecto)

    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 anterior, y así sucesivamente.

    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ás 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, consulta 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:

Acción
Descripción

"insert" (Default)

Inserta el documento en la colección de salida.

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

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 canalización de agregación, la etapa $merge lo genera automáticamente.

Por ejemplo, en la siguiente canalización de agregación, excluye$project el _id campo de los documentos que se pasan $merge a. Cuando $merge escribe estos documentos "newCollection" en, $merge genera un nuevo _id campo y 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 escribe el primer documento en la colección y es visible inmediatamente.

  • Si la agregación falla, cualquier escritura completada 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 sea el _id campo. Para usar un on valor de campo diferente para una colección que no existe, primero puede 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 desea especificar el commentDate campo como identificador:

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 $merge etapa puede generar una colección fragmentada. Cuando la colección de salida está fragmentada, $merge utiliza el _id campo y todos los campos de clave de fragmentación como identificador predeterminado. Si se anula el valor predeterminado, el identificador debe incluir todos los campos de clave de fragmentació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 moviesByYearAndRating colección contendrá documentos con estadísticas de películas por añoyear (campo) y clasificación de contenido (clave de fragmentación); específicamente, el identificador on es ["year", "rated"] (el orden de los campos no importa). Debido a $merge que requiere un índice único con claves que correspondan a los campos del identificador on, cree el índice único (el orden de los campos no importa): []1

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

Con la colección fragmentada moviesByYearAndRating y el índice único creado, puede usar $merge para mostrar los resultados de la agregación en esta colección, haciendo coincidir con [ "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 fragmentación cuando se pasa la opción { unique: true } si: la clave de fragmentación es basada en rango, la colección está vacía y no existe un índice único en la clave de fragmentación. En el ejemplo anterior, dado que el identificador on es la clave de fragmentació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 salida si los resultados de la agregación contienen uno o más 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 se especifica "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.

El error $merge se produce si el $merge da como resultado 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 produce un cambio en el valor de la clave de fragmentación de un documento existente.

Cualquier escritura completada por $merge antes del error no se revertirá.

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

Si el $merge intenta escribir un documento que viole algún índice único en la colección de salida, la operación generará 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.

Si se cumplen todas las condiciones siguientes para una etapa $merge, $merge inserta el documento directamente en la colección de salida:

  • El valor de whenMatched es una canalización de agregación,

  • El valor de whenNotMatched es insert, y

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

$merge inserta el documento directamente en la colección de salida.

Con la introducción $merge de, MongoDB proporciona dos etapas, $merge $outy, para escribir los resultados de la canalización 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.

  • 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 guarda los 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 puede considerarlo como un documento completamente nuevo, lo que resulta en actualizaciones adicionales. Para más información sobre este comportamiento, consulte Problema de Halloween.

$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

Una canalización de agregación no puede usar $merge dentro de una transacción.

Una canalización de agregación no puede usar $merge para generar una colección de series temporales.

Separate from materialized view

Una definición de vista no puede incluir la $merge etapa. Si la definición de vista incluye una canalización anidada (por ejemplo, la definición de vista incluye $facet la etapa), esta $merge restricción de la etapa también se aplica a las canalizaciones 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 usar junto con el nivel de consistencia de lectura "linearizable". Es decir, si especificas el "linearizable" nivel de consistencia de lectura para db.collection.aggregate(), no puedes incluir la etapa $merge en la pipeline.

Los ejemplos de esta página utilizan datos del conjunto de datos de muestra sample_mflix. Para obtener más información sobre cómo cargar este conjunto de datos en la implementación autogestionada de MongoDB, consultar Cargar el conjunto de datos de muestra. Si se realizó alguna modificación en las bases de datos de muestra, es posible que se deban descartar y volver a crear las bases de datos para ejecutar los ejemplos de esta página.

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

Nota

Para un conjunto de réplicas o una implementación independiente, si la base de datos de salida no existe, $merge también crea la base de datos.

Para una implementación de clúster particionado, la base de datos de salida especificada ya debe existir.

Puedes usar las $group $merge etapas y para crear una movieRatingSummary colección que resuma las películas aclamadas por la crítica por año de lanzamiento y clasificación de contenido:

db.movies.aggregate( [
{ $match: { metacritic: 100, rated: { $ne: null },
year: { $lte: 1972 } } },
{ $group: { _id: { year: "$year", rated: "$rated" },
count: { $sum: 1 } } },
{ $merge : { into: "movieRatingSummary", on: "_id",
whenMatched: "replace", whenNotMatched: "insert" } }
] )

El proceso utiliza las siguientes etapas:

  • $match etapa para filtrar películas aclamadas por la crítica estrenadas a través de 1972 con una calificación de contenido

  • $group etapa para agrupar las películas por year y rated

  • $merge etapa para escribir la salida de la $group etapa anterior movieRatingSummary en la colección de la sample_mflix base de datos

Para ver los documentos en la nueva colección movieRatingSummary:

db.movieRatingSummary.find().sort(
{ _id: 1 } )
[
{ _id: { year: 1939, rated: 'PASSED' }, count: 1 },
{ _id: { year: 1962, rated: 'PG' }, count: 1 },
{ _id: { year: 1963, rated: 'PG' }, count: 1 },
{ _id: { year: 1970, rated: 'R' }, count: 1 },
{ _id: { year: 1972, rated: 'R' }, count: 1 }
]

Para actualizar la colección movieRatingSummary del ejemplo anterior e incluir películas aclamadas por la crítica desde 1963 en adelante, esta canalización de agregación utiliza las siguientes etapas:

  • $match etapa para encontrar todas las películas metacritic: 100 con, una clasificación de contenido y un año de lanzamiento mayor o igual 1963 a.

  • $group etapa para agrupar las películas por year ratedy.

  • $merge para escribir el conjunto de resultados en la movieRatingSummary colección, reemplazando los documentos con el mismo _id valor. Para los documentos que no tienen coincidencias en la colección, $merge inserta los nuevos documentos.

db.movies.aggregate( [
{ $match: { metacritic: 100, rated: { $ne: null },
year: { $gte: 1963 } } },
{ $group: { _id: { year: "$year", rated: "$rated" },
count: { $sum: 1 } } },
{ $merge : { into: "movieRatingSummary", on: "_id",
whenMatched: "replace", whenNotMatched: "insert" } }
] )

Una vez finalizada la agregación, vea los documentos en la colección movieRatingSummary:

db.movieRatingSummary.find().sort(
{ _id: 1 } )
[
{ _id: { year: 1939, rated: 'PASSED' }, count: 1 },
{ _id: { year: 1962, rated: 'PG' }, count: 1 },
{ _id: { year: 1963, rated: 'PG' }, count: 1 },
{ _id: { year: 1970, rated: 'R' }, count: 1 },
{ _id: { year: 1972, rated: 'R' }, count: 1 },
{ _id: { year: 1982, rated: 'R' }, count: 1 },
{ _id: { year: 2014, rated: 'R' }, count: 1 }
]

Para garantizar que $merge no sobrescriba los datos existentes en la colección, establezca whenMatched en keepExisting o fail.

Una colección movieArchive en la base de datos sample_mflix contiene registros históricos de películas aclamadas por la crítica por año de estreno.

La colección movieArchive tiene un índice único en el campo year. Como máximo, debe existir un registro por año de lanzamiento:

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

Este proceso de agregación actualiza la colección movieArchive con datos de la colección movies para incluir películas aclamadas por la crítica desde 1963 en adelante. El proceso utiliza las siguientes etapas:

  • $match etapa para encontrar todas las películas metacritic: 100 con, una clasificación de contenido year >= 1963 y.

  • $group etapa para agrupar los títulos de las películas year por.

  • $project etapa para suprimir el _id campo y promover year a un campo de nivel superior. Cuando los documentos se pasan $merge a, $merge genera automáticamente un nuevo _id campo para los documentos.

  • $merge escribir el conjunto de resultados en movieArchive.

    La $merge etapa compara los documentos en el year campo y falla cuando encuentra coincidencia. Es decir, si ya existe un documento para ese año de lanzamiento, se $merge produce un error en la etapa.

db.movies.aggregate( [
{ $match: { metacritic: 100, rated: { $ne: null },
year: { $gte: 1963 } } },
{ $group: { _id: "$year",
titles: { $push: "$title" } } },
{ $project: { _id: 0, year: "$_id", titles: 1 } },
{ $merge : { into: "movieArchive", on: "year",
whenMatched: "fail" } }
] )

Si la movieArchive colección ya contiene un documento para cualquier año en el rango 1963–,2014 la agregación falla debido a un error de clave duplicada. Sin embargo, el proceso no revierte ningún documento que haya insertado antes del error.

Si especifica keepExisting para el documento coincidente, la agregación no afecta a dicho documento y no se produce un error de clave duplicada. Del mismo modo, si especifica replace, la operación no falla; sin embargo, reemplaza el documento existente.

Por defecto, si un documento en los resultados de la agregación coincide con un documento en la colección, la $merge etapa fusiona los documentos.

Puedes usar $merge para combinar los resultados de la colección movies y la colección comments para crear una nueva colección yearlyStats.

Para crear la colección yearlyStats, ejecute la siguiente canalización:

db.movies.aggregate( [
{ $match: { metacritic: 100, rated: { $ne: null },
year: { $gte: 1970, $lte: 1972 } } },
{ $group: { _id: "$year", movieCount: { $sum: 1 } } },
{ $merge : { into: "yearlyStats", on: "_id",
whenMatched: "merge", whenNotMatched: "insert" } }
])
Primera etapa:
La $match etapa filtra las películas aclamadas por la crítica ()metacritic: 100 con una clasificación de contenido, estrenadas 1970 entre 1972 y.
Segunda fase:
La etapa agrupa $group por year y cuenta las películas en un nuevo movieCount campo.
Tercera etapa:
La $merge etapa escribe los documentos yearlyStats en la colección de la misma base de datos. Si encuentra un documento existente en la colección que coincide con el _id campo, fusiona los documentos coincidentes. De lo contrario, inserta el documento. Para la creación inicial, no se encuentran documentos coincidentes.

Para ver los documentos en la colección, ejecute la siguiente operación:

db.yearlyStats.find().sort( { _id: 1 } )
[
{ _id: 1970, movieCount: 1 },
{ _id: 1972, movieCount: 1 }
]

De manera similar, ejecute la siguiente canalización de agregación en la colección comments para fusionar los recuentos de comentarios en la colección yearlyStats.

db.comments.aggregate( [
{ $match: { date: { $gte: new Date("1970-01-01"),
$lt: new Date("1973-01-01") } } },
{ $group: { _id: { $year: "$date" },
commentCount: { $sum: 1 } } },
{ $merge : { into: "yearlyStats", on: "_id",
whenMatched: "merge", whenNotMatched: "insert" } }
])
Primera etapa:
La $match etapa filtra los comentarios publicados entre 1970 y.1972
Segunda fase:
La etapa agrupa por año extraído del $group comentario date y cuenta los comentarios en un nuevo commentCount campo.
Tercera etapa:
La $merge etapa escribe los documentos yearlyStats en la colección de la misma base de datos. Si encuentra un documento existente en la colección que coincide con el _id campo (el año), fusiona los documentos coincidentes. De lo contrario, inserta el documento.

Para ver los documentos en la colección yearlyStats después de que los datos se hayan fusionado, ejecute la siguiente operación:

db.yearlyStats.find().sort( { _id: 1 } )
[
{ _id: 1970, movieCount: 1, commentCount: 889 },
{ _id: 1971, commentCount: 825 },
{ _id: 1972, movieCount: 1, commentCount: 863 }
]

El $merge puede usar una canalización de actualización personalizada cuando los documentos coinciden. La canalización whenMatched puede tener las siguientes etapas:

Una colección monthlyCommentTotals realiza un seguimiento del recuento acumulado de comentarios para cada mes.

Cada día llegan nuevos comentarios a la colección sample_mflix.comments. El siguiente proceso de agregación actualiza el total mensual con el recuento de comentarios de ese día:

db.comments.aggregate([
{ $match: { date: { $gte: new Date("1970-01-15"),
$lt: new Date("1970-01-16") } } },
{ $group: { _id: { $dateToString: { format: "%Y-%m",
date: "$date" } }, count: { $sum: 1 } } },
{ $merge: {
into: "monthlyCommentTotals",
on: "_id",
whenMatched: [
{ $addFields: {
count: { $add: [ "$count", "$$new.count" ] }
} }
],
whenNotMatched: "insert"
} }
])
Primera etapa:
La etapa encuentra todos los comentarios publicados el y el de $match enero.151970
Segunda fase:
La $group etapa agrupa los comentarios coincidentes por año-mes y los cuenta.
Tercera etapa:

La $merge etapa escribe los documentos monthlyCommentTotals en la colección. Si la etapa encuentra un documento existente en la colección que coincide con el _id campo, la etapa utiliza una canalización para agregar el del día count al total mensual existente.

  • Esta canalización no puede acceder directamente a los campos del documento de resultados. Para acceder al campo count en el documento de resultados, la canalización utiliza la variable $$new; es decir, $$new.count.

  • Esta canalización puede acceder directamente al campo count en el documento existente en la colección; es decir, $count.

El documento resultante sustituye al documento existente.

Para ver los documentos en la colección monthlyCommentTotals después de la operación de fusión, ejecute la siguiente operación:

db.monthlyCommentTotals.find()
[ { _id: '1970-01', count: 71 } ]

Puedes usar variables en el $merge campo whenMatched de la etapa. Las variables deben definirse antes de poder usarse.

Defina variables en uno o en ambos de los siguientes:

Para usar variables en 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.

Las pestañas a continuación demuestran el comportamiento cuando las variables se definen en la etapa de fusión, el comando de agregación, o en ambos.

Puedes definir variables en la $merge etapa y usar las variables en el campo whenMatched.

El siguiente ejemplo:

  • siembra una colección movieDetails con una película de la colección movies

  • ejecuta un comando que define aggregate una year variable en el $merge let y agrega el año a movieDetails usando whenMatched

  • retrieves the movieDetails document

db.movies.aggregate( [
{ $match: { title: "The Godfather" } },
{ $limit: 1 },
{ $project: { title: 1 } },
{ $merge: { into: "movieDetails", whenNotMatched: "insert" } }
] )
db.runCommand( {
aggregate: db.movieDetails.getName(),
pipeline: [ {
$merge: {
into: db.movieDetails.getName(),
let : { year: "2023" },
whenMatched: [ {
$addFields: { "addedYear": "$$year" }
} ]
}
} ],
cursor: {}
} )
db.movieDetails.find()
[ { _id: ..., title: 'The Godfather', addedYear: '2023' } ]

Nuevo en la versión 5.0.

Puedes definir variables en el aggregate comando let y usar las variables en el $merge campo whenMatched de la etapa.

El siguiente ejemplo:

  • siembra una colección movieDetails con una película de la colección movies

  • ejecuta un comando aggregate que define una variable year en el comando aggregate let y añade el año a movieDetails usando whenMatched

  • retrieves the movieDetails document

db.movies.aggregate( [
{ $match: { title: "The Godfather" } },
{ $limit: 1 },
{ $project: { title: 1 } },
{ $merge: { into: "movieDetails", whenNotMatched: "insert" } }
] )
db.runCommand( {
aggregate: db.movieDetails.getName(),
pipeline: [ {
$merge: {
into: db.movieDetails.getName(),
whenMatched: [ {
$addFields: { "addedYear": "$$year" }
} ]
}
} ],
cursor: {},
let : { year: "2023" }
} )
db.movieDetails.find()
[ { _id: ..., title: 'The Godfather', addedYear: '2023' } ]

Puedes definir variables en la $merge etapa y, a partir de MongoDB,5.0 el aggregate comando.

Si se definen dos variables con el mismo nombre en la $merge etapa y en aggregate el comando,$merge se utiliza la variable de la etapa.

En este ejemplo, la canalización utiliza year: "2023" en lugar de la year: "2019" aggregate variable de comando:

db.movies.aggregate( [
{ $match: { title: "The Godfather" } },
{ $limit: 1 },
{ $project: { title: 1 } },
{ $merge: { into: "movieDetails", whenNotMatched: "insert" } }
] )
db.runCommand( {
aggregate: db.movieDetails.getName(),
pipeline: [ {
$merge: {
into: db.movieDetails.getName(),
let : { year: "2023" },
whenMatched: [ {
$addFields: { "addedYear": "$$year" }
} ]
}
} ],
cursor: {},
let : { year: "2019" }
} )
db.movieDetails.find()
[ { _id: ..., title: 'The Godfather', addedYear: '2023' } ]

Los ejemplos de C# en esta página utilizan la base de datos sample_mflix de los conjuntos de datos de muestra de Atlas. Para aprender a crear un clúster gratuito de MongoDB Atlas y cargar los conjuntos de datos de muestra, consulta Primeros pasos en la documentación del controlador de MongoDB .NET/C#.

La siguiente clase Movie modela los documentos en la colección sample_mflix.movies:

public class Movie
{
public ObjectId Id { get; set; }
public int Runtime { get; set; }
public string Title { get; set; }
public string Rated { get; set; }
public List<string> Genres { get; set; }
public string Plot { get; set; }
public ImdbData Imdb { get; set; }
public int Year { get; set; }
public int Index { get; set; }
public string[] Comments { get; set; }
[BsonElement("lastupdated")]
public DateTime LastUpdated { get; set; }
}

Nota

ConventionPack para Pascal Case

Las clases de C# en esta página utilizan Pascal case para los nombres de sus propiedades, pero los nombres de los campos en la colección de MongoDB utilizan camel case. Para tener en cuenta esta diferencia, se puede usar el siguiente código para registrar un ConventionPack cuando la aplicación se inicie:

var camelCaseConvention = new ConventionPack { new CamelCaseElementNameConvention() };
ConventionRegistry.Register("CamelCase", camelCaseConvention, type => true);

Para usar el driver de MongoDB .NET/C# para agregar una etapa $merge a un pipeline de agregación, llama al método Merge() en un objeto PipelineDefinition.

Cuando se llame al método Merge(), se debe pasar una instancia de la clase MergeStageOptions. Este objeto permite especificar opciones para la etapa $merge, como la forma de gestionar documentos coincidentes.

El siguiente ejemplo crea una etapa del pipeline que fusiona los documentos del pipeline en la colección movies. El objeto MergeStageOptions especifica las siguientes opciones:

  • La opción OnFieldNames especifica que la operación debe usar los campos "id" y "title" para encontrar documentos coincidentes en la colección de origen y en la colección movies.

  • La opción WhenMatched especifica que si un documento en la colección fuente coincide con un documento en la colección movies, debe reemplazar el documento en la colección movies.

  • La opción WhenNotMatched especifica que si un documento en la colección fuente no coincide con un documento en la colección movies, debe insertarse en la colección movies.

var movieCollection = client
.GetDatabase("sample_mflix")
.GetCollection<Movie>("movies");
var pipeline = new EmptyPipelineDefinition<Movie>()
.Merge(movieCollection,
new MergeStageOptions<Movie>(
{
OnFieldNames = new List<string>() {"id", "title"},
WhenMatched = MergeStageWhenMatched.Replace,
WhenNotMatched = MergeStageWhenNotMatched.Insert,
});

Los ejemplos de Node.js en esta página utilizan la base de datos sample_mflix de los conjuntos de datos de muestra de Atlas. Para aprender a crear un clúster gratuito de MongoDB Atlas y cargar los conjuntos de datos de muestra, consulte Primeros pasos en la documentación del controlador de MongoDB Node.js.

Para utilizar el controlador de MongoDB Node.js para agregar una etapa de $merge a una canalización de agregación, utilice el Operador $merge en un objeto de canalización.

El siguiente ejemplo crea una etapa de pipeline que fusiona los documentos del pipeline en la colección movies. El ejemplo incluye los siguientes campos:

  • La opción on especifica que la operación debe usar los campos "_id" y "title" para encontrar documentos coincidentes en la colección de origen y en la colección movies.

  • La opción whenMatched especifica que si un documento en la colección fuente coincide con un documento en la colección movies, reemplaza el documento en la colección movies.

  • La opción whenNotMatched especifica que si un documento en la colección de origen no coincide con un documento en la colección movies, la operación inserta el documento en la colección movies.

A continuación, el ejemplo ejecuta la canalización de agregación:

const pipeline = [
{
$merge: {
into: "movies",
on: ["_id", "title"],
whenMatched: "replace",
whenNotMatched: "insert"
}
}
];
const cursor = collection.aggregate(pipeline);
return cursor;

Volver

Coincidencia

En esta página