Definició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.
$mergeEscribe los resultados de la canalización de agregación en una colección especificada. El operador
$mergedebe 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.
Tenga en cuenta los siguientes puntos al utilizar las
$mergeetapas o en$outuna canalización de agregación:A partir de MongoDB 5.0, los pipelines con una etapa
$mergepueden ejecutarse en nodos secundarios del set de réplicas si todos los nodos del clúster tienen la featureCompatibilityVersion establecida en5.0o superior y la preferencia de lectura permite lecturas secundarias.En versiones anteriores de MongoDB, los pipelines con etapas de
$outo$mergesiempre 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 que también genera los resultados de la agregación en una
$outcolección,consulte$mergey Comparación.$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.
Compatibilidad
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.
Sintaxis
$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:
Si la colección de salida no existe,
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:
Para el campo o los campos especificados:
El valor por defecto de on depende de la colección de salida:
| |||||||||||
Opcional. El comportamiento de Se puede especificar cualquiera de los dos:
| |||||||||||
Opcional. Especifica las variables que se utilizarán en la secuencia whenMatched. Especifica un documento con los nombres de las variables y las expresiones de valores: Si Para acceder a las variables en la canalización whenMatched: Se debe especificar el prefijo del signo de dólar doble ($$) junto con el nombre de la variable en el formato Para ver ejemplos, consulte la sección "Usar variables para personalizar la fusión". | |||||||||||
Opcional. El comportamiento de Puedes especificar una de las cadenas de acción predefinidas:
|
Considerations
_id Generación de campos
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" } } ] )
Crear una nueva colección si la colección de salida no existe
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
$mergeguarda el primer documento a la colección y es visible inmediatamente.Si la agregación falla, cualquier guardado completado por el
$mergeantes 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" } } ] )
Salida a una colección fragmentada
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 usted anula 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 moviesByYearAndRating colección contendrá documentos con estadísticas de películas por añoyear (campo) y clasificación de contenido (clave de fragmento); 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 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 En el ejemplo anterior, debido a que el identificador |
Reemplazar documentos ($merge) vs. Reemplazar colección ($out)
$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 on. 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.
Documentos existentes y _id y valores de la clave de partición
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 _id campo, elimine el _id campo en los resultados de la agregación para evitar el error, como con una etapa precedente, y así $unset 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á.
Restricciones de índice único
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 guardar un documento que viola algún índice único en la colección de salida, la operación genera un error. Por ejemplo:
Insertar un documento no coincidente que viola un índice único distinto del índice en el campo(s).
Reemplaza un documento existente por un nuevo documento que infrinja un índice único distinto al índice en el(los) campo(s) on.
Fusionar los documentos coincidentes que resultan en un documento que viola un índice único distinto del índice en el en campo(s).
Validación de esquema
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.
whenMatched Comportamiento del pipeline
$merge inserta el documento directamente en la colección de salida cuando se cumplen todas las condiciones siguientes:
El valor de whenMatched es una canalización de agregación.
El valor de whenNotMatched
insertes.No hay coincidencia para un documento en la colección de salida.
$merge y comparación $out
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 | |
|---|---|
|
|
|
|
|
|
|
|
|
|
Salida a la misma colección que está siendo agregada
Advertencia
Cuando$mergeenvía la salida a la misma colección que se está agregando, los documentos pueden actualizarse varias veces o la operación puede generar un bucle infinito. Este comportamiento se produce cuando la actualización realizada por$mergecambia la ubicación física de los documentos almacenados en el disco. Cuando cambia la ubicación física de un documento, $mergepuede considerarlo como un documento completamente nuevo, lo que genera actualizaciones adicionales. Para obtener más información sobre este comportamiento, consulte el Problema de Halloween.
$merge puede generar una salida a la misma colección que se está agregando. También puede generar una salida a una colección que aparece en otras etapas de la canalización,$lookup como.
Restricciones
Restricciones | Descripción |
|---|---|
La pipeline de agregación no puede usar | |
Un pipeline de agregación no puede usar | |
ver definición | Una definición de vista no puede incluir la etapa |
| El pipeline anidado de la etapa |
| El pipeline anidado de la etapa |
| El pipeline anidado de la etapa |
|