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

$merge (estágio de agregação )

Observação

Esta página descreve o estágio $merge, que gera resultados do pipeline de agregação para uma coleção. Para o operador $mergeObjects, que mescla documentos em um único documento, consulte $mergeObjects.

$merge

Grava os resultados do pipeline de agregação para uma coleção especificada. O operador $merge deve ser o último estágio do pipeline.

O estágio $merge:

  • Pode enviar para uma coleção no mesmo banco de dados ou em um banco de dados diferente.

  • Pode gerar saída para a mesma coleção que está sendo agregada. Para obter mais informações, consulte Saída para a mesma coleção que está sendo agregada.

  • Considere os seguintes pontos ao usar os estágios $merge ou $out em um pipeline de agregação:

    • A partir do MongoDB 5.0, os pipelines com um estágio $merge poderão ser executados em nós secundários do conjunto de réplicas se todos os nós do cluster tiverem o featureCompatibilityVersion definido como 5.0 ou superior e a preferência de leitura permitir leituras secundárias.

      • $merge e os estágios $out são executados em nós secundários, mas as operações de gravação são enviadas para o nó primário.

      • Nem todas as versões do driver suportam operações $merge enviadas aos nós secundários. Para obter detalhes, consulte a documentação do driver.

    • nas versões anteriores do MongoDB , os pipelines com estágios $out ou $merge sempre são executados no nó principal, e a preferência de leitura não é considerada.

  • Cria uma nova coleta se a coleta de saída ainda não existir.

  • Pode incorporar resultados (inserir novos documentos, mesclar documentos, substituir documentos, manter documentos existentes, falhar a operação, processar documentos com um pipeline de atualização personalizado) a uma coleção existente.

  • Pode gerar saída para uma coleção fragmentada. A coleta de entrada também pode ser fragmentada.

Para uma comparação com o estágio $out, que também gera os resultados da agregação em uma coleção, consulte $merge e $out Comparação.

Observação

Visualizações materializadas sob demanda

$merge pode incorporar os resultados do pipeline em uma coleção de saída existente em vez de executar uma substituição completa da coleção. Essa funcionalidade permite que os usuários criem exibições materializadas sob demanda, em que o conteúdo da coleção de saída é atualizado de forma incremental quando o pipeline é executado.

Para obter mais informações sobre esse caso de uso, consulte Exibições materializadas sob demanda , bem como os exemplos nesta página.

As visualizações materializadas são separadas das exibições somente para leitura. Para obter informações sobre como criar visualizações somente para leitura, consulte exibições somente para leitura.

Você pode utilizar o $merge para implantações hospedadas nos seguintes ambientes:

  • MongoDB Atlas: o serviço totalmente gerenciado para implantações do MongoDB na nuvem

  • MongoDB Enterprise: a versão autogerenciada e baseada em assinatura do MongoDB

  • MongoDB Community: uma versão com código disponível, de uso gratuito e autogerenciada do MongoDB

$merge tem a seguinte sintaxe:

{ $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 exemplo:

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

Se utilizar todas as opções padrão para $merge, inclusive gravar em uma coleção no mesmo banco de dados, você poderá utilizar o formulário simplificado:

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

O estágio $merge recebe um documento com os seguintes campos:

Campo
Descrição

A coleção de saída. Especifique uma das seguintes opções:

  • O nome da coleção como uma string para saída para uma coleção no mesmo banco de dados onde a agregação é executada. Por exemplo:

    into: "myOutput"

  • O nome do banco de dados e da coleção em um documento para saída para uma coleção no banco de dados especificado. Por exemplo:

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

Se a coleção de saída não existir, o $merge criará a coleção:

  • Para um conjunto de réplicas ou um standalone, se o banco de dados de saída não existir, $merge também criará o banco de dados.

  • Para um cluster fragmentado, o banco de dados de saída especificado já deve existir.

A coleção de saída pode ser uma coleção fragmentada.

Opcional. Campo ou campos que atuam como um identificador exclusivo para um documento. O identificador determina se um documento de resultados corresponde a um documento existente na coleta de resultados. Especifique uma das seguintes opções:

  • Um único nome de campo como uma string. Por exemplo:

    on: "_id"

  • Uma combinação de campos em uma array. Por exemplo:

    on: [ "date", "customerId" ]
    The order of the fields in the array does not matter, and you cannot specify the same field multiple times.

Para o campo ou campos especificados:

  • Os documentos de resultados da agregação devem conter o(s) campo(s) especificado(s) em on, a menos que o campo on seja o campo _id. Se o campo _id estiver faltando em um documento de resultados, o MongoDB o adicionará automaticamente.

  • Para sistemas que executam o MongoDB 8.0 e versões anteriores, o campo ou os campos especificados para on não podem estar ausentes ou conter um valor nulo. A partir do MongoDB 8.1, se o índice de suporte não for esparso, o campo ou campos especificados para on podem estar ausentes ou conter um valor nulo.

  • O campo ou campos especificados não podem conter um valor de array.

$merge requer um índice único com chaves que correspondam aos campos do identificador ligado. Embora a ordem da especificação da chave do índice não seja importante, o índice único deve conter somente os campos on como suas chaves.

  • O índice também deve ter o mesmo agrupamento que o agrupamento da agregação.

  • O índice exclusivo pode ser um índice esparso .

  • O índice único não pode ser um índice parcial.

  • Para coleções de saída que já existem, o índice correspondente já deve existir.

O valor padrão para ativado depende da coleta de saída:

  • Se a coleção de saída não existir, o identificador on deverá ser e será padronizado para o _id campo . O índice _id exclusivo correspondente é criado automaticamente.

    • Para usar um campo de identificador diferente em uma coleção que não existe, você pode criar a coleção primeiro, criando um índice único no(s) campo(s) desejado(s). Consulte a seção sobre coleta de saída inexistente para obter um exemplo.

    • A partir do MongoDB 8.3, o servidor verifica se o índice _id criado automaticamente corresponde ao agrupamento da query. Se os agrupamentos não corresponderem, o índice _id não poderá fornecer exclusividade para a query e a query não será executada.

  • Se a coleção de saída existente não estiver fragmentada, o identificador on assumirá como padrão o campo _id.

  • Se a coleção de saída existente for uma coleção fragmentada, o identificador ligado _id terá como padrão todos os campos de chave fragmentada e o campo. Se especificar um identificador on diferente, o on deverá conter todos os campos de chave de fragmento.

Opcional. O comportamento de $merge se um documento de resultado e um documento existente na coleção tiverem o mesmo valor para o(s) campo(s) especificado(s) ligado(s).

Você pode especificar:

  • Uma das strings de ação predefinidas:

    em ação
    Descrição

    Substitua o documento existente na coleção de resultados pelo documento de resultados correspondente.

    Ao executar uma substituição, o documento de substituição não pode resultar em uma modificação do valor _id ou, se a coleção de saída for fragmentada, o valor da chave de estilhaço. Caso contrário, a operação gera um erro.

    Para evitar esse erro, se o campo on não incluir o _id campo, remova o _id campo nos resultados da agregação para evitar o erro, como em um $unset estágio de anterior e assim por diante.

    Mantenha o documento existente na coleção de resultados.

    "merge" (Padrão)

    Mesclar os documentos correspondentes (semelhante ao operador $mergeObjects).

    • Se o documento de resultados contiver campos que não estejam no documento existente, adicione esses novos campos ao documento existente.

    • Se o documento de resultados contiver campos no documento existente, substitua os valores de campo existentes pelos valores do documento de resultados.

    Por exemplo, se a coleção de saída tiver o documento:

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

    E os resultados da agregação tiverem o documento:

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

    Em seguida, o documento mesclado é:

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

    Ao realizar uma mesclagem, o documento mesclado não pode resultar em uma modificação do valor _id ou, se a coleção de saída for fragmentada, do valor da chave fragmentada. Caso contrário, a operação gera um erro.

    Para evitar esse erro, se o campo on não incluir o _id campo, remova o _id campo nos resultados da agregação para evitar o erro, como em um $unset estágio de anterior e assim por diante.

    Pare e falhe a operação de agregação. Quaisquer alterações na coleção de saída de documentos anteriores não serão revertidas.

  • Um pipeline de agregação para atualizar o documento na coleção.

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

    O pipeline só pode consistir nas seguintes etapas:

    O pipeline não pode modificar o valor do campo ligado. Por exemplo, se você estiver correspondendo no campo month, o pipeline não poderá modificar o campo month.

    O whenMatched pipeline pode acessar diretamente os campos dos documentos existentes na coleção de saída utilizando $<field>.

    Para acessar os campos a partir dos documentos de resultados de agregação, use:

    • A variável $$new embutida para acessar o campo. Especificamente, $$new.<field>. A $$new variável só estará disponível se a especificação let for omitida.

    • As variáveis definidas pelo usuário no campo let .

      Especifique o prefixo do sinal de dólar duplo ($$) juntamente com o nome da variável no formulário $$<variable_name>. Por exemplo, $$year. Se a variável estiver definida para um documento, você também poderá incluir um campo de documento no formulário $$<variable_name>.<field>. Por exemplo, $$year.month.

      Para obter mais exemplos, consulte Usar variáveis para personalizar a fusão.

Opcional. Especifica variáveis para uso no pipeline whenMatched.

Especifique um documento com os nomes de variáveis e expressões de valor:

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

Se não for especificado,{ new: "$$ROOT" } ROOTo padrão será (consulte). O pipeline whenMatched pode acessar a $$new variável .

Para acessar as variáveis no pipeline whenMatched:

Especifique o prefixo do sinal de dólar duplo ($$) juntamente com o nome da variável no formulário $$<variable_name>. Por exemplo, $$year. Se a variável estiver definida para um documento, você também poderá incluir um campo de documento no formulário $$<variable_name>.<field>. Por exemplo, $$year.month.

Para obter exemplos, consulte Usar variáveis para personalizar a fusão.

Opcional. O comportamento de $merge se um documento de resultado não corresponder a um documento existente na coleção de saída.

Você pode especificar uma das strings de ação predefinidas:

em ação
Descrição

"insert" (Default)

Insira o documento na coleção de saída.

Descarte o documento. Especificamente, o $merge não insere o documento na coleção de resultados.

Pare e falhe a operação de agregação. Quaisquer alterações já gravadas na coleção de saída não serão revertidas.

Se o campo _id não estiver presente em um documento dos resultados do pipeline de agregação, o estágio $merge o gerará automaticamente.

Por exemplo, no seguinte pipeline de agregação, $project exclui o campo _id dos documentos passados para $merge. Quando $merge grava esses documentos para o "newCollection", $merge gera um novo campo _id e um novo valor.

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

A operação $merge cria uma nova coleção se a coleção de saída especificada não existir.

  • A coleção de saída é criada quando $merge grava o primeiro documento na coleção e fica imediatamente visível.

  • Se a agregação falhar, quaisquer gravações concluídas pelo $merge antes do erro não serão revertidas.

Observação

Para um conjunto de réplicas ou um standalone, se o banco de dados de saída não existir, $merge também criará o banco de dados.

Para um cluster fragmentado, o banco de dados de saída especificado já deve existir.

Se a coleção de saída não existir, $merge exige que o identificador ligado seja o campo _id. Para usar um valor de campo on diferente para uma coleção que não existe, você pode criar a coleção primeiro criando um índice exclusivo nos campos desejados. Por exemplo, se a coleção de saída newDailyCommentCount não existir e você quiser especificar o campo commentDate como o identificador ligado:

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" } }
] )

O estágio $merge pode gerar saída para uma coleção fragmentada. Quando a coleção de saída é fragmentada, $merge usa o campo _id e todos os campos da chave de shard com hash como identificador padrão. Se você substituir o padrão, o identificador ligado deverá incluir todos os campos de chave de shard com hash:

{ $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 exemplo, utilize o método sh.shardCollection() para criar uma nova coleção fragmentada moviesByYearAndRating com o campo rated como a chave fragmentada.

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

A coleção moviesByYearAndRating conterá documentos com estatísticas de filmes de acordo com o ano (campo year) e classificação de conteúdo (chave de shard com hash); especificamente, o identificador ligado é ["year", "rated"] (a ordem dos campos não importa). Como $merge exige um índice único com chaves que correspondem aos campos do identificador ligado, crie o índice único (a ordem dos campos não importa): [1]

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

Com a coleção fragmentada moviesByYearAndRating e o índice único criado, você pode usar $merge para gerar os resultados da agregação para essa coleção, correspondendo a [ "year", "rated" ], como neste exemplo:

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] O método sh.shardCollection() também pode criar um índice exclusivo na chave de estilhaço quando a opção { unique: true } for passada se: a chave de estilhaço for baseada em intervalo, a coleção estiver vazia e um índice exclusivo na chave de estilhaço ainda não existir. No exemplo anterior, como o identificador on é a chave de estilhaço e outro campo, uma operação separada para criar o índice correspondente é necessária.

$merge pode substituir um documento existente na coleção de saída se os resultados da agregação contiverem um documento ou documentos que correspondam com base na especificação ligada. Como tal, $merge pode substituir todos os documentos na coleção existente se os resultados da agregação incluírem documentos correspondentes para todos os documentos existentes na coleção e você especificar "substituir" para whenMatched.

No entanto, para substituir uma coleção existente, independentemente dos resultados da agregação, use $out em vez disso.

Os erros do $merge se o $merge resultar em uma alteração no valor de _id de um documento existente.

Dica

Para evitar esse erro, se o campo on não contiver o campo _id, remova o campo _id dos resultados da agregação para evitar o erro, como em um estágio $unset anterior e assim por diante.

Além disso, para uma coleção fragmentada, $merge também gera um erro se resultar em uma alteração no valor da chave fragmentada de um documento existente.

As gravações concluídas pelo $merge antes do erro não serão revertidas.

Se o índice único usado por $merge para campo(s) ligado(s) for descartado no meio da agregação, não haverá garantias de que a agregação será eliminada. Se a agregação continuar, não haverá garantias de que os documentos não tenham valores de campo on duplicados.

Se o $merge tentar gravar um documento que viole qualquer índice exclusivo na coleção de saída, a operação gerará um erro. Por exemplo:

Se sua coleção usar validação de esquema e tiver validationAction definido como error, inserir um documento inválido ou atualizar um documento com valores inválidos com $merge gerará um MongoServerError e o documento não será gravado na coleção de destino. Se houver vários documentos inválidos, apenas o primeiro documento inválido encontrado gerará um erro. Todos os documentos válidos são gravados na coleção de destino e todos os documentos inválidos não são gravados.

Se todos os itens a seguir forem verdadeiros para um estágio $merge, $merge insere o documento diretamente na coleção de saída:

  • O valor de whenMatched é um pipeline de agregação,

  • O valor de whenNotMatched é insert, e

  • Não há correspondência para um documento na coleta de saída,

$merge insere o documento diretamente na coleta de saída.

Com a introdução de $merge, o MongoDB fornece dois estágios, $merge e $out, para gravar os resultados do pipeline de agregação em uma coleção:

$merge
  • Pode enviar para uma coleção no mesmo banco de dados ou em um banco de dados diferente.

  • Pode enviar para uma coleção no mesmo banco de dados ou em um banco de dados diferente.

  • Cria uma nova coleta se a coleta de saída ainda não existir.

  • Cria uma nova coleta se a coleta de saída ainda não existir.

  • Pode incorporar resultados (inserir novos documentos, mesclar documentos, substituir documentos, manter documentos existentes, falhar a operação, processar documentos com um pipeline de atualização personalizado) a uma coleção existente.

  • Substitui completamente a coleção de saída se ela já existir.

  • Pode gerar saída para uma coleção fragmentada. A coleta de entrada também pode ser fragmentada.

  • Não é possível gerar saída para uma coleção fragmentada. A coleção de entrada, no entanto, pode ser fragmentada.

  • Corresponde a declarações SQL:

    • MERGE.

    • INSERT INTO T2 SELECT FROM T1.

    • SELECT INTO T2 FROM T1.

    • Criar/Atualizar visualizações materializadas.

  • Corresponde à declaração SQL:

    • INSERT INTO T2 SELECT FROM T1.

    • SELECT INTO T2 FROM T1.

Aviso

Quando $merge gera saídas para a mesma coleção que está sendo agregada, os documentos podem ser atualizados várias vezes ou a operação pode resultar em um loop infinito. Esse comportamento ocorre quando a atualização executada por $merge altera a localização física dos documentos armazenados no disco. Quando a localização física de um documento muda, $merge pode considerá-lo um documento totalmente novo, resultando em atualizações adicionais. Para obter mais informações sobre esse comportamento, consulte Problema de Halloween.

$merge pode gerar saída para a mesma coleção que está sendo agregada. Você também pode gerar saída para uma coleção que aparece em outros estágios do pipeline, como $lookup.

Restrições
Descrição

Um pipeline de agregação não pode usar $merge dentro de uma transação.

Um pipeline de agregação não pode usar $merge para gerar uma coleção de séries temporais.

Separate from materialized view

Uma definição de visualização não pode incluir o estágio $merge. Se a definição de visualização incluir pipeline aninhado (por exemplo, a definição de visualização inclui o estágio $facet), essa restrição de estágio $merge também se aplica aos pipelines aninhados.

$lookup estágio

O $lookup estágio do pipeline aninhado não pode incluir o estágio $merge.

$facet estágio

O $facet estágio do pipeline aninhado não pode incluir o estágio $merge.

$unionWith estágio

O $unionWith estágio do pipeline aninhado não pode incluir o estágio $merge.

"linearizable" Leia a preocupação

O estágio $merge não pode ser usado em conjunto com a read concern "linearizable". Ou seja, se você especificar "linearizable" read concern para db.collection.aggregate(), não poderá incluir o estágio $merge no pipeline.

Os exemplos nesta página usam dados do conjunto de dados de amostra sample_mflix. Para obter detalhes sobre como carregar esse conjunto de dados em sua implantação autogerenciada do MongoDB , consulte Carregar o conjunto de dados de amostra. Se você fez modificações nos bancos de dados de amostra, talvez seja necessário descartar e recriar os bancos de dados para executar os exemplos nesta página.

Se a coleção de saída não existir, o $merge criará a coleção.

Observação

Para um conjunto de réplicas ou uma implantação autônoma, se o banco de dados de saída não existir, $merge também criará o banco de dados.

Para uma implantação de cluster fragmentado, o banco de dados de saída especificado já deve existir.

Você pode usar os $group e $merge estágios para criar uma coleção movieRatingSummary que resume filmes aclamados pela crítica por ano de lançamento e classificação de conteúdo:

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" } }
] )

O pipeline usa as seguintes etapas:

  • $match estágio para filtrar filmes aclamados pela crítica lançados por meio de 1972 com uma classificação de conteúdo

  • Estágio $group para agrupar os filmes por year e rated

  • $merge estágio para gravar a saída do estágio $group precedente na coleção movieRatingSummary no banco de dados sample_mflix

Para visualizar os documentos na nova coleção 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 atualizar a coleção de movieRatingSummary do exemplo anterior para incluir filmes aclamados pela crítica a partir de 1963, este pipeline de agregação utiliza os seguintes estágios:

  • Estágio $match para encontrar todos os filmes com metacritic: 100, uma classificação de conteúdo e um ano de lançamento maior ou igual a 1963.

  • $group estágio para agrupar os filmes por year e rated.

  • $merge para gravar o conjunto de resultados na coleção movieRatingSummary, substituindo documentos com o mesmo valor de _id. Para documentos que não têm correspondências na coleção, o $merge insere os novos 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" } }
] )

Após a execução da agregação, exiba os documentos na coleção 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 garantir que o $merge não substitua os dados existentes na coleção, configure whenMatched para keepExisting ou fail.

Uma coleção movieArchive no banco de dados sample_mflix contém registros históricos de filmes aclamados pela crítica de acordo com o ano de lançamento.

A coleção movieArchive tem um índice único no campo year. No máximo, deve existir um registro por ano de lançamento:

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

Este pipeline de agregação atualiza a coleção movieArchive com dados da coleção movies para incluir filmes aclamados pela crítica a partir de 1963. O pipeline usa os seguintes estágios:

  • Estágio $match para encontrar todos os filmes com metacritic: 100, uma classificação de conteúdo e year >= 1963.

  • $group para agrupar os títulos dos filmes por year.

  • Estágio $project para suprimir o campo _id e promover year a um campo de nível superior. Quando os documentos são passados para $merge, $merge gera automaticamente um novo campo _id para os documentos.

  • $merge para gravar o conjunto de resultados em movieArchive.

    O estágio $merge faz a correspondência dos documentos no campo year e falha quando houver correspondência. Ou seja, se já existir um documento para esse ano de lançamento, o $merge apresenta erro.

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" } }
] )

Se a coleção movieArchive já contiver um documento de qualquer ano na faixa 1963–2014, a agregação falhará devido ao erro de chave duplicada. No entanto, o pipeline não reverte nenhum documento inserido antes do erro.

Se você especificar keepExisting para o documento correspondente, a agregação não afetará o documento correspondente e não apresentará erro com erro de chave duplicada. Da mesma forma, se você especificar substituir, a operação não falhará; no entanto, a operação substituirá o documento existente.

Por padrão, se um documento nos resultados de agregação corresponder a um documento na coleção, o estágio $merge mescla os documentos.

Você pode usar $merge para mesclar os resultados da coleção movies e da coleção comments para criar uma nova coleção yearlyStats.

Para criar a coleção yearlyStats, execute o seguinte pipeline:

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" } }
])
Primeiro estágio:
Os filtros do estágio $match para filmes aclamados pela crítica (metacritic: 100) com classificação indicativa, lançados entre 1970 e 1972.
Segundo estágio:
O estágio $group agrupa por year e conta filmes em um novo campo movieCount.
Terceiro estágio:
O estágio $merge grava os documentos na coleção yearlyStats no mesmo banco de dados. Se o estágio encontrar um documento existente na coleção que corresponda ao campo _id, o estágio mesclará os documentos correspondentes. Caso contrário, o estágio insere o documento. Para a criação inicial, nenhum documento corresponde.

Para visualizar os documentos na coleção, execute a seguinte operação:

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

Da mesma forma, execute o seguinte pipeline de agregação na coleção comments para mesclar as contagens de comentários na coleção 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" } }
])
Primeiro estágio:
O estágio $match filtra para comentários postados entre 1970 e 1972.
Segundo estágio:
O estágio $group agrupa por ano extraído do comentário date e conta comentários em um novo campo commentCount.
Terceiro estágio:
O estágio $merge grava os documentos na coleção yearlyStats no mesmo banco de dados. Se o estágio encontrar um documento existente na coleção que corresponda ao campo _id (o ano), o estágio mesclará os documentos correspondentes. Caso contrário, o estágio insere o documento.

Para visualizar os documentos na coleção yearlyStats após os dados terem sido mesclados, execute a seguinte operação:

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

O $merge pode usar um pipeline de atualização personalizado quando os documentos correspondem. O pipeline whenMatched pode ter os seguintes estágios:

Uma coleção monthlyCommentTotals acompanha a contagem contínua de comentários para cada mês.

Todos os dias, novos comentários chegam à coleção sample_mflix.comments. O pipeline de agregação a seguir atualiza o total mensal com a contagem de comentários desse dia:

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"
} }
])
Primeiro estágio:
O estágio $match encontra todos os comentários postados em janeiro 15, 1970.
Segundo estágio:
O estágio $group agrupa os comentários por ano-mês e os conta.
Terceiro estágio:

O estágio $merge grava os documentos na coleção monthlyCommentTotals. Se o estágio encontrar um documento existente na coleção que corresponda ao campo _id, o estágio usa um pipeline para adicionar o count do dia ao total mensal existente.

  • Esse pipeline não pode acessar diretamente os campos do documento de resultados. Para acessar o campo count no documento de resultados, o pipeline usa a variável $$new; ou seja, $$new.count.

  • Esse pipeline pode acessar diretamente o campo count no documento existente na coleção; ou seja, $count.

O documento resultante substitui o documento existente.

Para visualizar documentos na coleção monthlyCommentTotals após a operação de mesclagem, execute a seguinte operação:

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

Você pode usar variáveis no campo whenMatched do estágio $merge. As variáveis precisam ser definidas para poderem ser usadas.

Defina variáveis em uma ou em ambas as opções a seguir:

Para usar variáveis em whenMatched:

Especifique o prefixo do sinal de dólar duplo ($$) juntamente com o nome da variável no formulário $$<variable_name>. Por exemplo, $$year. Se a variável estiver definida para um documento, você também poderá incluir um campo de documento no formulário $$<variable_name>.<field>. Por exemplo, $$year.month.

As guias abaixo demonstram o comportamento quando as variáveis são definidas no estágio de mesclagem, no comando de agregação ou em ambos.

Você pode definir variáveis no estágio $merge let e usar as variáveis no campo whenMatched.

O seguinte exemplo:

  • semeia uma coleção movieDetails com um filme da coleção movies

  • executa um comando aggregate que define uma variável year no $merge let e adiciona o ano 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' } ]

Novidades na versão 5.0.

Você pode definir variáveis no comando aggregate let e usar as variáveis no campo whenMatched do estágio $merge.

O seguinte exemplo:

  • semeia uma coleção movieDetails com um filme da coleção movies

  • executa um comando aggregate que define uma variável year no comando aggregate let e adiciona o ano 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' } ]

Você pode definir variáveis no estágio $merge e, a partir do MongoDB 5.0, no comando aggregate.

Se duas variáveis com o mesmo nome forem definidas no estágio $merge e no comando aggregate, a variável de estágio $merge será usada.

Neste exemplo, o pipeline usa year: "2023" em vez da variável de comando year: "2019" aggregate:

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' } ]

A classe Movie a seguir modela os documentos usados neste exemplo:

[BsonIgnoreExtraElements]
public class Movie
{
[BsonId]
public ObjectId Id { get; set; }
[BsonElement("title")]
public string Title { get; set; } = null!;
[BsonElement("year")]
public int? Year { get; set; }
[BsonElement("runtime")]
public int? Runtime { get; set; }
[BsonElement("rated")]
public string? Rated { get; set; }
[BsonElement("metacritic")]
public int Metacritic { get; set; }
[BsonElement("plot")]
public string? Plot { get; set; }
[BsonElement("type")]
public string? Type { get; set; }
[BsonElement("cast")]
public string[]? Cast { get; set; }
[BsonElement("directors")]
public string[]? Directors { get; set; }
[BsonElement("writers")]
public string[]? Writers { get; set; }
[BsonElement("imdb")]
public ImdbData? Imdb { get; set; }
}

Para usar o driver MongoDB .NET/C# para adicionar um estágio $merge a um pipeline de agregação, chame o método Merge() em um objeto PipelineDefinition.

Ao chamar o Merge() método, você deve passar uma instância da classe MergeStageOptions . Este objeto permite especificar opções para o estágio $merge, como lidar com documentos correspondentes.

O exemplo a seguir cria um estágio de pipeline que mescla os documentos no pipeline na coleção movies. O objeto MergeStageOptions especifica as seguintes opções:

  • A opção OnFieldNames especifica que a operação deve usar o campo "_id" para identificar documentos correspondentes.

  • A opção WhenMatched especifica que, se um documento na coleção de origem corresponder a um documento na coleção de destino, a operação substituirá o documento correspondente.

  • A opção WhenNotMatched especifica que, se um documento na coleção de origem não corresponder a um documento na coleção de destino, a operação inserirá o documento na coleção de destino.

var pipeline = new EmptyPipelineDefinition<Movie>()
.Merge(_targetCollection,
new MergeStageOptions<Movie>()
{
OnFieldNames = new List<string>() { "_id" },
WhenMatched = MergeStageWhenMatched.Replace,
WhenNotMatched = MergeStageWhenNotMatched.Insert,
});
{ "_id": "...", "title": "Back to the Future", "metacritic": 96 }
{ "_id": "...", "title": "Jurassic Park", "metacritic": 68 }
{ "_id": "...", "title": "The Shawshank Redemption", "metacritic": 80 }

Os exemplos do Node.js nesta página utilizam o banco de dados do sample_mflix a partir dos conjuntos de dados de amostra do Atlas. Para saber como criar um cluster gratuito do MongoDB Atlas e carregar os conjuntos de dados de exemplo, consulte Introdução na documentação do driver do MongoDB Node.js

Para usar o driver Node.js do MongoDB para adicionar um estágio $merge a um pipeline de agregação , use o operador $merge em um objeto de pipeline.

O exemplo a seguir cria um estágio de pipeline que mescla os documentos no pipeline na coleção movies. O exemplo inclui os seguintes campos:

  • A opção on especifica que a operação deve usar os campos "_id" e "title" para localizar documentos correspondentes na coleção de origem e na coleção movies.

  • A opção whenMatched especifica que, se um documento na coleção de origem corresponder a um documento na coleção movies, ele substituirá o documento na coleção movies.

  • A opção whenNotMatched especifica que, se um documento na collection de origem não corresponder a um documento na collection movies, a operação inserirá o documento na collection movies.

Em seguida, o exemplo executa o agregação pipeline:

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

Voltar

$match

Nesta página