Menu Docs

Página inicial do DocsDesenvolver aplicaçõesManual do MongoDB

encontrar e modificar

Nesta página

  • Definição
  • Compatibilidade
  • Sintaxe
  • Campos de comando
  • Saída
  • Comportamento
  • Exemplos
findAndModify

O comando findAndModify atualiza e retorna um único documento. Por padrão, o documento retornado não inclui as modificações feitas na atualização. Para retornar o documento com as modificações feitas na atualização, use a opção new .

Dica

Em mongosh, esse comando também pode ser executado por meio do método auxiliar db.collection.findAndModify() .

Os métodos auxiliares são convenientes para os usuários mongosh , mas podem não retornar o mesmo nível de informações que os comandos do banco de dados. Nos casos em que a conveniência não for necessária ou os campos de retorno adicionais forem necessários, use o comando de banco de dados.

Este comando está disponível em sistemas hospedados nos seguintes ambientes:

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

Observação

Este comando é suportado em todos os clusters do MongoDB Atlas. Para obter informações sobre todos os comandos, consulte Comandos não suportados.

Alterado na versão 5.0.

O comando tem a seguinte sintaxe:

db.runCommand(
{
findAndModify: <collection-name>,
query: <document>,
sort: <document>,
remove: <boolean>,
update: <document or aggregation pipeline>,
new: <boolean>,
fields: <document>,
upsert: <boolean>,
bypassDocumentValidation: <boolean>,
writeConcern: <document>,
maxTimeMS: <integer>,
collation: <document>,
arrayFilters: <array>,
hint: <document|string>,
comment: <any>,
let: <document> // Added in MongoDB 5.0
}
)

O comando utiliza os seguintes campos:

Campo
Tipo
Descrição
query
documento

Opcional. Os critérios de seleção para a modificação. O campo query emprega os mesmos seletores de query usados no método db.collection.find() . Embora a query possa corresponder a vários documentos, findAndModify selecionará somente um documento para atualizar.

Se não for especificado, o padrão será um documento vazio.

A partir do MongoDB 4.2 (e 4.0.12+, 3.6.14+, e 3.4.23+), a operação resulta em erro se o argumento de query não for um documento.

sort

documento

Opcional. Determina qual documento a operação atualiza se a query selecionar vários documentos. findAndModify atualiza o primeiro documento na ordem de classificação especificada por este argumento.

A partir do MongoDB 4.2 (e 4.0.12+, 3.6.14+, e 3.4.23+), a operação resulta em erro se o argumento de classificação não for um documento.

O MongoDB não armazena documentos em uma collection em uma ordem específica. Ao ordenar em um campo que contém valores duplicados, os documentos que contêm esses valores podem ser retornados em qualquer ordem.

Se desejar uma ordem de classificação consistente, inclua pelo menos um campo em sua ordenação que contenha valores exclusivos. A maneira mais fácil de garantir isso é incluir o campo _id em sua query de ordenação.

Consulte Consistência de classificação para obter mais informações.

remove
boleano
Deve especificar o campo remove ou update. Remove o documento especificado no campo query. Define como true para remover o documento selecionado. O padrão é false.
update
documento ou array

Deve especificar o campo remove ou update. Executa uma atualização do documento selecionado.

new
boleano
Opcional. Quando true, retorna o documento atualizado em vez do original. O padrão é false.
fields
documento

Opcional. Um subconjunto de campos para retornar. O documento fields especifica uma inclusão de um campo com 1, como em: fields: { <field1>: 1, <field2>: 1, ... }. Consulte projeção.

A partir do MongoDB 4.2 (e 4.0.12+, 3.6.14+, e 3.4.23+), a operação resulta em erro se o argumento de campos não for um documento.

upsert
boleano

Opcional. Usado em conjunto com o campo update.

Quando true, findAndModify ou:

  • Cria um novo documento se nenhum documento corresponder a query. Para obter mais detalhes, consulte comportamento upsert.

  • Atualiza um único documento que corresponda a query.

Para evitar várias upserts, certifique-se de que o(s) campo(s) query seja(m) indexado(s) exclusivamente. Consulte Upsert com índice exclusivo para obter um exemplo.

O padrão é false, que não insere um novo documento quando nenhuma correspondência é encontrada.

bypassDocumentValidation
boleano
Opcional. Habilita o findAndModify para ignorar a validação do documento durante a operação. Isso permite atualizar documentos que não atendem aos requisitos de validação.
writeConcern
documento

Opcional. Um documento que expressa o write concern. Omitir para usar o write concern padrão.

Não defina explicitamente a preocupação de gravação para a operação se for executada em uma transação. Para usar write concern com transações, consulte Transações e write concern.

maxTimeMS
número inteiro não negativo

Opcional.

Especifica um limite de tempo em milissegundos. Se você não especificar um valor para maxTimeMS, as operações não atingirão o tempo limite. Um valor 0 especifica explicitamente o comportamento ilimitado padrão.

O MongoDB encerra as operações que excedem o limite de tempo alocado usando o mesmo mecanismo de db.killOp(). O MongoDB só encerra uma operação em um de seus pontos de interrupção designados.

findAndModify
string
A collection contra a qual executar o comando.
collation
documento

Opcional.

Especifica o agrupamento a ser usado para a operação.

A colocação permite que os usuários especifiquem regras específicas do idioma para comparação de strings, como regras para letras maiúsculas e marcas de acento.

A opção de agrupamento tem a seguinte sintaxe:

collation: {
locale: <string>,
caseLevel: <boolean>,
caseFirst: <string>,
strength: <int>,
numericOrdering: <boolean>,
alternate: <string>,
maxVariable: <string>,
backwards: <boolean>
}

Ao especificar agrupamento, o campo locale é obrigatório; todos os outros campos de agrupamento são opcionais. Para obter descrições dos campos, consulte Documento de agrupamento.

Se o agrupamento não for especificado, mas a coleção tiver um agrupamento padrão (consulte db.createCollection()), a operação usará o agrupamento especificado para a coleção.

Se nenhum agrupamento for especificado para a collection ou para as operações, o MongoDB usa a comparação binária simples usada nas versões anteriores para comparações de strings.

Você não pode especificar vários agrupamentos para uma operação. Por exemplo, você não pode especificar agrupamentos diferentes por campo ou, se estiver realizando uma busca com uma classificação, não poderá usar um agrupamento para a busca e outro para a classificação.

arrayFilters
variedade

Opcional. Uma matriz de documentos de filtro que determina quais elementos da matriz modificar para uma operação de atualização em um campo da matriz.

No documento de upgrade, use o operador posicional filtrado $[<identifier>] para definir um identificador, que você então faz referência nos documentos do filtro de matriz. Você não pode ter um documento de filtro de matriz para um identificador se o identificador não estiver incluído no documento de atualização.

Observação

O <identifier> deve começar com uma letra minúscula e conter apenas caracteres alfanuméricos.

Você pode incluir o mesmo identificador várias vezes no documento de atualização; entretanto, para cada identificador distinto ($[identifier]) no documento de atualização, você deve especificar exatamente um documento de filtro de matriz correspondente. Ou seja, não é possível especificar vários documentos de filtro de matriz para o mesmo identificador. Por exemplo, se a instrução de atualização incluir o identificador x (possivelmente várias vezes), você não poderá especificar o seguinte para arrayFilters que inclui 2 documentos de filtro separados para x:

// INVALID
[
{ "x.a": { $gt: 85 } },
{ "x.b": { $gt: 80 } }
]

No entanto, você pode especificar condições compostas no mesmo identificador em um único documento de filtro, como nos exemplos a seguir:

// Example 1
[
{ $or: [{"x.a": {$gt: 85}}, {"x.b": {$gt: 80}}] }
]
// Example 2
[
{ $and: [{"x.a": {$gt: 85}}, {"x.b": {$gt: 80}}] }
]
// Example 3
[
{ "x.a": { $gt: 85 }, "x.b": { $gt: 80 } }
]

Por exemplo, consulte Operações de atualização de array com arrayFilters.

Observação

arrayFilters não está disponível para atualizações que usam um pipeline de agregação.

hint
documento ou string

Opcional. Um documento ou string que especifica o índice para utilizar para suportar o query.

A opção pode usar um documento de especificação de índice ou a string do nome do índice.

Se você especificar um índice que não existe, a operação ocorrerá erros.

Para um exemplo, consulte Especificar hint para Operações do findAndModify .

comment
qualquer

Opcional. Um comentário fornecido pelo usuário para anexar a este comando. Depois de definido, esse comentário aparece junto com os registros desse comando nos seguintes locais:

Um comentário pode ser qualquer tipo BSON válido (string, inteiro, objeto, array etc).

documento

Opcional.

Especifica um documento com uma lista de variáveis. Isso permite que você melhore a legibilidade do comando separando as variáveis do texto da query.

A sintaxe do documento é:

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

A variável é definida para o valor retornado pela expressão e não pode ser alterada posteriormente.

Para acessar o valor de uma variável no comando, use o prefixo de dois cifrões ($$) junto com o nome da variável no formato $$<variable_name>. Por exemplo: $$targetTotal.

Observação

Para usar uma variável para filtrar os resultados, você deve acessar a variável dentro do operador $expr.

Para obter um exemplo completo usando let e variáveis, consulte Usar variáveis em let.

Novidades na versão 5,0.

O comando findAndModify retorna um documento com os seguintes campos:

Campo
Tipo
Descrição
value
documento
Contém o valor retornado do comando. Consulte value para obter detalhes.
lastErrorObject
documento
Contém informações sobre documentos atualizados. Consulte lastErrorObject para obter detalhes.
ok
número
Contém o status de execução da comando. 1 em caso de sucesso ou 0 se ocorrer um erro.

O documento incorporado do lastErrorObject contém os seguintes campos:

Campo
Tipo
Descrição
n
inteiro
Contém o número de documentos que corresponderam ao predicado de atualização ou o número de documentos que o comando inseriu ou excluiu.
updatedExisting
boleano

Contém true se uma operação do update:

  • Atualizou um documento existente.

  • Encontrado o documento, mas ele já estava no estado de destino desejado, então nenhuma atualização realmente ocorreu.

upserted
documento
Contém o ObjectId do documento inserido se uma operação do update com upsert: true resultou em um novo documento.

Para operações do remove, o value contém o documento removido se a query corresponder a um documento. Se a query não corresponder a um documento para remover, value conterá null.

Para operações do update, o documento embutido do value contém o seguinte:

  • Se o parâmetro new não estiver configurado ou for false:

    • o documento de pré-modificação se a query corresponder a um documento;

    • caso contrário, null.

  • Se new for true:

    • o documento atualizado se a query retornar uma correspondência;

    • o documento inserido se upsert: true e nenhum documento corresponder à query;

    • caso contrário, null.

Os upserts podem criar documentos duplicados, a menos que haja um índice único para evitar duplicatas.

Considere um exemplo em que nenhum documento com o nome Andy existe e vários clientes emitem o seguinte comando ao mesmo tempo:

db.runCommand(
{
findAndModify: "people",
query: { name: "Andy" },
update: { $inc: { score: 1 } },
upsert: true
}
)

Se todas as operações findAndModify concluírem a fase de query antes que qualquer cliente insira dados com êxito e não houver nenhum índice único no campo name , cada operação findAndModify poderá resultar em uma inserção, criando vários documentos com name: Andy.

Um índice exclusivo no campo name garante que apenas um documento seja criado. Com um índice único em vigor, as operações múltiplas findAndModify agora exibem o seguinte comportamento:

  • Exatamente uma operação findAndModify inserirá com êxito um novo documento.

  • Outras operações findAndModify atualizam o documento recém-inserido ou falham devido a uma colisão de chave exclusiva.

    Para que outras operações do findAndModify atualizem o documento recém-inserido, todas as seguintes condições devem ser atendidas:

    • A collection de destino tem um índice único que causaria um erro de chave duplicado.

    • A operação de atualização não é updateMany ou multi é false.

    • A condição de correspondência de atualização é:

      • Um único predicado de igualdade. Por exemplo { "fieldA" : "valueA" }

      • Um E lógico de predicados de igualdade. Por exemplo { "fieldA" : "valueA", "fieldB" : "valueB" }

    • O campo no predicado de igualdade correspondem ao campo no padrão de chave de índice único.

    • A operação de atualização não modifica nenhum campo no padrão de chave de índice único.

A tabela a seguir mostra exemplos de operações upsert que, quando ocorre uma colisão de chaves, resultam em uma atualização ou falha.

Padrão de chave de índice exclusivo
Operação de atualização
Resultado
{ name : 1 }
db.people.updateOne(
{ name: "Andy" },
{ $inc: { score: 1 } },
{ upsert: true }
)
O campo score do documento correspondente é incrementado em 1.
{ name : 1 }
db.people.updateOne(
{ name: { $ne: "Joe" } },
{ $set: { name: "Andy" } },
{ upsert: true }
)
A operação falha porque modifica o campo no padrão de chave de índice único (name).
{ name : 1 }
db.people.updateOne(
{ name: "Andy", email: "andy@xyz.com" },
{ $set: { active: false } },
{ upsert: true }
)
A operação falha porque os campos de predicados de igualdade (name, email) não correspondem ao campo chave de índice (name).

Para usar findAndModify em uma collection fragmentada:

  • Se você só tiver como alvo um shard, pode usar uma chave de shard parcial no campo query ou,

  • Você pode fornecer uma condição de igualdade em uma chave de shard completa no campo query.

  • A partir da versão 7.1, você não precisa fornecer a chave de shard ou o campo _id na especificação da query.

documento em uma collection fragmentada podem não ter os campo principais do fragmento. Para direcionar um documento que não tenha a chave de shard, você pode usar a null correspondência de igualdade em conjunto com outra condição de filtro (como no campo _id ). Por exemplo:

{ _id: <value>, <shardkeyfield>: null } // _id of the document missing shard key

A partir do MongoDB 4,2, você pode atualizar o valor da chave do fragmento de um documento, a menos que o campo da chave do fragmento seja o campo imutável _id. No MongoDB 4.2 e anterior, o valor de campo chave de fragmento de um documento é imutável.

Aviso

Documento em collection fragmentadas podem não ter os campo da chave de fragmento. Tenha cuidado para não remover acidentalmente a chave de fragmento ao alterar o valor da chave de fragmento de um documento.

Para atualizar o valor da chave do fragmento existente com findAndModify:

Os documentos em uma collection fragmentada podem não ter os campos de chave de shard. Para usar findAndModify para definir a chave de shard ausente do documento:

  • Você deve executar em um mongos. Não emita a operação diretamente no fragmento.

  • Você deve executar em uma transação ou como retryable write se o novo valor da chave de shard não for null.

  • Você deve incluir um filtro de igualdade na chave de shard completa.

Dica

Como um valor de chave ausente é retornado como parte de uma correspondência de igualdade nula, para evitar a atualização de uma chave de valor nulo, inclua condições de consulta (como no campo _id) conforme apropriado.

Veja também:

O comando findAndModify adiciona suporte para a opção bypassDocumentValidation , que permite a você ignorar a validação do documento ao inserir ou atualizar documentos em uma coleção com regras de validação.

Ao atualizar um documento, findAndModify e o método updateOne() operam de forma diferente:

  • Se vários documentos corresponderem aos critérios de atualização, para findAndModify, você poderá especificar uma sort para dar alguma medida de controle sobre qual documento atualizar.

    updateOne() atualiza o primeiro documento que corresponde.

  • Por padrão, o findAndModify retorna um objeto que contém a versão pré-modificada do documento, como também, o status da operação. Para obter o documento atualizado, use a opção new .

    O método updateOne() retorna um objeto WriteResult() que contém o status da operação.

    Para retornar o documento atualizado, use o método find(). No entanto, outras atualizações podem ter modificado o documento entre a atualização e a recuperação do documento. Além disso, se a atualização modificou apenas um único documento, mas vários documentos corresponderam, você precisará usar lógica adicional para identificar o documento atualizado.

Ao modificar um único documento, findAndModify e o método updateOne() atualizam atomicamente o documento. Consulte Atomicidade e transações para obter mais detalhes sobre as interações e a ordem das operações desses métodos.

Dica

Veja também:

findAndModify pode ser usado dentro de transações distribuídas.

Importante

Na maioria dos casos, uma transação distribuída incorre em um custo de desempenho maior do que as gravações de um único documento, e a disponibilidade de transações distribuídas não deve substituir o design eficaz do esquema. Em muitos cenários, o modelo de dados desnormalizado (documentos e arrays incorporados) continuará a ser ideal para seus dados e casos de uso. Ou seja, para muitos cenários, modelar seus dados adequadamente minimizará a necessidade de transações distribuídas.

Para considerações adicionais sobre o uso de transações (como limite de tempo de execução e limite de tamanho do oplog), consulte também Considerações de produção.

Você pode criar collection e índices dentro de uma transação distribuída se a transação não for uma transação de escrita cross-shard.

findAndModify com upsert: true pode ser executado em uma coleção existente ou uma coleção não existente. Se for executada em uma coleção inexistente, a operação cria a coleção.

Não defina explicitamente a preocupação de gravação para a operação se for executada em uma transação. Para usar write concern com transações, consulte Transações e write concern.

O comando a seguir atualiza um documento existente na collection people onde o documento corresponde aos critérios do query:

db.runCommand(
{
findAndModify: "people",
query: { name: "Tom", state: "active", rating: { $gt: 10 } },
sort: { rating: 1 },
update: { $inc: { score: 1 } }
}
)

Este comando executa as seguintes ações:

  1. A query localiza um documento na collection people onde o campo name tem o valor Tom, o campo state tem o valor active e o campo rating tem um valor greater than 10.

  2. Os sort encomendam os resultados da query em ordem crescente. Se vários documentos atenderem à condição query, o comando selecionará para modificação o primeiro documento conforme ordenado por este sort.

  3. O update increments o valor do campo score por 1.

  4. O comando retorna um documento com os seguintes campos:

    • O campo lastErrorObject que contém os detalhes do comando, incluindo o campo updatedExisting que é true, e

    • O campo value que contém o original (ou seja, pré-modificação) documento selecionado para esta atualização:

      {
      "lastErrorObject" : {
      "connectionId" : 1,
      "updatedExisting" : true,
      "n" : 1,
      "syncMillis" : 0,
      "writtenTo" : null,
      "err" : null,
      "ok" : 1
      },
      value" : {
      "_id" : ObjectId("54f62d2885e4be1f982b9c9c"),
      "name" : "Tom",
      "state" : "active",
      "rating" : 100,
      "score" : 5
      },
      "ok" : 1
      }

Para retornar o documento atualizado no campo value , adicione a opção new:true ao comando.

Se nenhum documento corresponder à condição query, o comando retornará um documento que contenha null no campo value:

{ "value" : null, "ok" : 1 }

mongosh e muitos drivers fornecem um método auxiliar findAndModify() . Utilizando o auxiliar de shell, esta operação anterior pode assumir o seguinte formulário:

db.people.findAndModify( {
query: { name: "Tom", state: "active", rating: { $gt: 10 } },
sort: { rating: 1 },
update: { $inc: { score: 1 } }
} );

No entanto, o assistente de shell findAndModify() retorna somente o documento não modificado ou, se new for true, o documento atualizado.

{
"_id" : ObjectId("54f62d2885e4be1f982b9c9c"),
"name" : "Tom",
"state" : "active",
"rating" : 100,
"score" : 5
}

O comando findAndModify a seguir inclui a opção upsert: true para a operação update atualizar um documento correspondente ou, se não houver nenhum documento correspondente, criar um novo documento:

db.runCommand(
{
findAndModify: "people",
query: { name: "Gus", state: "active", rating: 100 },
sort: { rating: 1 },
update: { $inc: { score: 1 } },
upsert: true
}
)

Se o comando encontrar um documento correspondente, o comando executará uma atualização.

Se o comando não encontrar um documento correspondente, a operação update com upsert: true resultará em uma inserção e retornará um documento com os seguintes campos:

  • O campo lastErrorObject que contém os detalhes do comando, incluindo o campo upserted que contém o valor _id do documento recém-inserido e

  • O campo value contendo null.

{
"value" : null,
"lastErrorObject" : {
"updatedExisting" : false,
"n" : 1,
"upserted" : ObjectId("54f62c8bc85d4472eadea26f")
},
"ok" : 1
}

O comando findAndModify a seguir inclui a opção upsert: true e a opção new:true . O comando atualiza um documento correspondente e retorna o documento atualizado ou, se não existir nenhum documento correspondente, insere um documento e retorna o documento recém-inserido no campo value .

No exemplo a seguir, nenhum documento na collection people corresponde à condição query:

db.runCommand(
{
findAndModify: "people",
query: { name: "Pascal", state: "active", rating: 25 },
sort: { rating: 1 },
update: { $inc: { score: 1 } },
upsert: true,
new: true
}
)

O comando retorna o documento recém-inserido no campo value:

{
"lastErrorObject" : {
"connectionId" : 1,
"updatedExisting" : false,
"upserted" : ObjectId("54f62bbfc85d4472eadea26d"),
"n" : 1,
"syncMillis" : 0,
"writtenTo" : null,
"err" : null,
"ok" : 1
},
"value" : {
"_id" : ObjectId("54f62bbfc85d4472eadea26d"),
"name" : "Pascal",
"rating" : 25,
"state" : "active",
"score" : 1
},
"ok" : 1
}

Ao incluir uma especificação sort no campo rating, o exemplo seguinte remove da collection people um único documento com o valor state de active e o menor rating entre os documentos correspondentes:

db.runCommand(
{
findAndModify: "people",
query: { state: "active" },
sort: { rating: 1 },
remove: true
}
)

O comando retorna o documento excluído:

{
"lastErrorObject" : {
"connectionId" : 1,
"n" : 1,
"syncMillis" : 0,
"writtenTo" : null,
"err" : null,
"ok" : 1
},
"value" : {
"_id" : ObjectId("54f62a6785e4be1f982b9c9b"),
"name" : "XYZ123",
"score" : 1,
"state" : "active",
"rating" : 3
},
"ok" : 1
}

A colocação permite que os usuários especifiquem regras específicas do idioma para comparação de strings, como regras para letras maiúsculas e marcas de acento.

Uma coleção myColl possui os seguintes documentos:

{ _id: 1, category: "café", status: "A" }
{ _id: 2, category: "cafe", status: "a" }
{ _id: 3, category: "cafE", status: "a" }

A seguinte operação inclui a opção coleção:

db.runCommand(
{
findAndModify: "myColl",
query: { category: "cafe", status: "a" },
sort: { category: 1 },
update: { $set: { status: "Updated" } },
collation: { locale: "fr", strength: 1 }
}
)

A operação retorna o seguinte documento:

{
"lastErrorObject" : {
"updatedExisting" : true,
"n" : 1
},
"value" : {
"_id" : 1,
"category" : "café",
"status" : "A"
},
"ok" : 1
}

Observação

arrayFilters não está disponível para atualizações que usam um pipeline de agregação.

A partir do MongoDB 3,6, ao atualizar um campo de array, você pode especificar arrayFilters que determina quais elementos da array devem ser atualizados.

Observação

arrayFilters não está disponível para atualizações que usam um pipeline de agregação.

Crie uma collection students com os seguintes documentos:

db.students.insertMany( [
{ "_id" : 1, "grades" : [ 95, 92, 90 ] },
{ "_id" : 2, "grades" : [ 98, 100, 102 ] },
{ "_id" : 3, "grades" : [ 95, 110, 100 ] }
] )

Para atualizar todos os elementos que são maiores ou iguais a 100 na array grades , utilize o operador posicional $[<identifier>] com a opção arrayFilters :

db.runCommand(
{
findAndModify: "students",
query: { grades: { $gte: 100 } },
update: { $set: { "grades.$[element]" : 100 } },
arrayFilters: [ { "element": { $gte: 100 } } ]
}
)

A operação atualiza o campo grades para um único documento e, após a operação, a collection tem os seguintes documentos:

{ "_id" : 1, "grades" : [ 95, 92, 90 ] }
{ "_id" : 2, "grades" : [ 98, 100, 100 ] }
{ "_id" : 3, "grades" : [ 95, 110, 100 ] }

Observação

arrayFilters não está disponível para atualizações que usam um pipeline de agregação.

Crie uma collection students2 com os seguintes documentos:

db.students2.insertMany( [
{
"_id" : 1,
"grades" : [
{ "grade" : 80, "mean" : 75, "std" : 6 },
{ "grade" : 85, "mean" : 90, "std" : 4 },
{ "grade" : 85, "mean" : 85, "std" : 6 }
]
},
{
"_id" : 2,
"grades" : [
{ "grade" : 90, "mean" : 75, "std" : 6 },
{ "grade" : 87, "mean" : 90, "std" : 3 },
{ "grade" : 85, "mean" : 85, "std" : 4 }
]
}
] )

A operação a seguir localiza um documento em que o campo _id é igual a 1 e usa o operador posicional filtrado $[<identifier>] com arrayFilters para atualizar o mean para todos os elementos na array grades onde a nota é maior maior ou igual a 85.

db.runCommand(
{
findAndModify: "students2",
query: { _id : 1 },
update: { $set: { "grades.$[elem].mean" : 100 } },
arrayFilters: [ { "elem.grade": { $gte: 85 } } ]
}
)

A operação atualiza o campo grades para um único documento e, após a operação, a collection tem os seguintes documentos:

{
"_id" : 1,
"grades" : [
{ "grade" : 80, "mean" : 75, "std" : 6 },
{ "grade" : 85, "mean" : 100, "std" : 4 },
{ "grade" : 85, "mean" : 100, "std" : 6 }
]
}
{
"_id" : 2,
"grades" : [
{ "grade" : 90, "mean" : 75, "std" : 6 },
{ "grade" : 87, "mean" : 90, "std" : 3 },
{ "grade" : 85, "mean" : 85, "std" : 4 }
]
}

A partir do MongoDB 4.2, findAndModify pode aceitar um aggregation pipeline para a atualização. O pipeline pode consistir nas seguintes etapas:

O uso do aggregation pipeline permite uma instrução de atualização mais expressiva, como atualizações condicionais Express com base em valores de campo atuais ou atualização de um campo usando o valor de outro(s) campo(s).

Por exemplo, criar uma collection students2 com os seguintes documentos:

db.students2.insertMany( [
{
"_id" : 1,
"grades" : [
{ "grade" : 80, "mean" : 75, "std" : 6 },
{ "grade" : 85, "mean" : 90, "std" : 4 },
{ "grade" : 85, "mean" : 85, "std" : 6 }
]
},
{
"_id" : 2,
"grades" : [
{ "grade" : 90, "mean" : 75, "std" : 6 },
{ "grade" : 87, "mean" : 90, "std" : 3 },
{ "grade" : 85, "mean" : 85, "std" : 4 }
]
}
] )

A operação a seguir localiza um documento em que o campo _id é igual a 1 e usa um aggregation pipeline para calcular um novo total de campo a partir do campo grades:

db.runCommand(
{
findAndModify: "students2",
query: { "_id" : 1 },
update: [ { $set: { "total" : { $sum: "$grades.grade" } } } ],
new: true
}
)

Observação

O $set usado no pipeline se refere ao estágio de aggregation $set e não ao operador de atualização $set.

Após a operação, a coleção conta com os seguintes documentos:

{
"_id" : 1,
"grades" : [ { "grade" : 80, "mean" : 75, "std" : 6 }, { "grade" : 85, "mean" : 90, "std" : 4 }, { "grade" : 85, "mean" :85, "std" : 6 } ],
"total" : 250
}
{
"_id" : 2,
"grades" : [ { "grade" : 90, "mean" : 75, "std" : 6 }, { "grade" : 87, "mean" : 90, "std" : 3 }, { "grade" : 85, "mean" : 85,"std" : 4 } ]
}

No mongosh, crie uma coleção do members com os seguintes documentos:

db.members.insertMany( [
{ "_id" : 1, "member" : "abc123", "status" : "P", "points" : 0, "misc1" : null, "misc2" : null },
{ "_id" : 2, "member" : "xyz123", "status" : "A", "points" : 60, "misc1" : "reminder: ping me at 100pts", "misc2" : "Some random comment" },
{ "_id" : 3, "member" : "lmn123", "status" : "P", "points" : 0, "misc1" : null, "misc2" : null },
{ "_id" : 4, "member" : "pqr123", "status" : "D", "points" : 20, "misc1" : "Deactivated", "misc2" : null },
{ "_id" : 5, "member" : "ijk123", "status" : "P", "points" : 0, "misc1" : null, "misc2" : null },
{ "_id" : 6, "member" : "cde123", "status" : "A", "points" : 86, "misc1" : "reminder: ping me at 100pts", "misc2" : "Some random comment" }
] )

Crie os seguintes índices na coleção:

db.members.createIndex( { status: 1 } )
db.members.createIndex( { points: 1 } )

A operação a seguir sugere explicitamente o uso do índice { status: 1 }:

db.runCommand({
findAndModify: "members",
query: { "points": { $lte: 20 }, "status": "P" },
remove: true,
hint: { status: 1 }
})

Observação

Se você especificar um índice que não existe, a operação ocorrerá erros.

Para visualizar o índice utilizado, execute o explain na operação:

db.runCommand(
{
explain: {
findAndModify: "members",
query: { "points": { $lte: 20 }, "status": "P" },
remove: true,
hint: { status: 1 }
},
verbosity: "queryPlanner"
}
)

Novidades na versão 5,0.

Para definir variáveis que você pode acessar em outro lugar no comando, use a opção let .

Observação

Para filtrar resultados usando uma variável, você deve acessar a variável dentro do operador $expr.

Criar uma coleção cakeFlavors:

db.cakeFlavors.insertMany( [
{ _id: 1, flavor: "chocolate" },
{ _id: 2, flavor: "strawberry" },
{ _id: 3, flavor: "cherry" }
] )

O exemplo a seguir define uma variável targetFlavor em let e usa a variável para alterar o sabor do bolo de cereja para laranja:

db.cakeFlavors.runCommand( {
findAndModify: db.cakeFlavors.getName(),
query: { $expr: { $eq: [ "$flavor", "$$targetFlavor" ] } },
update: { flavor: "orange" },
let: { targetFlavor: "cherry" }
} )
← find